From c281ee3b61e8ab53ff118866d72618ae8cce582b Mon Sep 17 00:00:00 2001
From: Christopher Speller
Date: Mon, 13 Mar 2017 12:54:22 -0400
Subject: [PATCH] Updating server dependancies. Also adding
github.com/jaytaylor/html2text and gopkg.in/gomail.v2 (#5748)
---
glide.lock | 40 +-
glide.yaml | 4 +
vendor/github.com/goamz/goamz/aws/aws.go | 1 +
vendor/github.com/goamz/goamz/aws/regions.go | 23 +
vendor/github.com/goamz/goamz/sqs/sqs.go | 2 +
.../golang/protobuf/descriptor/descriptor.go | 2 +-
.../protobuf/descriptor/descriptor_test.go | 2 +-
.../protobuf/protoc-gen-go/testdata/Makefile | 6 +-
.../protoc-gen-go/testdata/my_test/test.pb.go | 7 +-
.../testdata/my_test/test.pb.go.golden | 7 +-
.../github.com/jaytaylor/html2text/.gitignore | 24 +
.../jaytaylor/html2text/.travis.yml | 14 +
vendor/github.com/jaytaylor/html2text/LICENSE | 22 +
.../github.com/jaytaylor/html2text/README.md | 116 +
.../jaytaylor/html2text/html2text.go | 312 +
.../jaytaylor/html2text/html2text_test.go | 674 +
.../jaytaylor/html2text/testdata/utf8.html | 22 +
.../html2text/testdata/utf8_with_bom.xhtml | 24 +
vendor/github.com/lib/pq/README.md | 2 +-
vendor/github.com/lib/pq/conn.go | 92 +-
vendor/github.com/lib/pq/conn_go18.go | 35 +-
vendor/github.com/lib/pq/conn_test.go | 108 +-
vendor/github.com/lib/pq/go18_test.go | 15 +-
.../github.com/lib/pq/listen_example/doc.go | 24 +-
vendor/github.com/lib/pq/notify_test.go | 24 +-
vendor/github.com/lib/pq/oid/types.go | 12 +
vendor/github.com/lib/pq/ssl.go | 123 +-
vendor/github.com/lib/pq/ssl_permissions.go | 16 +-
vendor/github.com/lib/pq/ssl_test.go | 198 +-
vendor/github.com/lib/pq/ssl_windows.go | 10 +-
vendor/github.com/miekg/dns/README.md | 4 +
vendor/github.com/miekg/dns/client.go | 20 +-
vendor/github.com/miekg/dns/client_test.go | 63 +-
vendor/github.com/miekg/dns/clientconfig.go | 32 +
.../github.com/miekg/dns/clientconfig_test.go | 37 +
.../github.com/miekg/dns/compress_generate.go | 184 +
vendor/github.com/miekg/dns/dane.go | 9 +-
vendor/github.com/miekg/dns/dns_test.go | 17 +
vendor/github.com/miekg/dns/dnssec.go | 21 +-
vendor/github.com/miekg/dns/dnssec_keygen.go | 16 +-
vendor/github.com/miekg/dns/dnssec_keyscan.go | 2 +-
vendor/github.com/miekg/dns/edns.go | 12 +-
vendor/github.com/miekg/dns/idn/punycode.go | 3 -
vendor/github.com/miekg/dns/msg.go | 188 +-
vendor/github.com/miekg/dns/nsecx.go | 11 +-
vendor/github.com/miekg/dns/parse_test.go | 6 +-
vendor/github.com/miekg/dns/reverse.go | 4 +-
vendor/github.com/miekg/dns/scan.go | 8 +-
vendor/github.com/miekg/dns/scan_rr.go | 116 +-
vendor/github.com/miekg/dns/server_test.go | 4 +-
vendor/github.com/miekg/dns/sig0.go | 5 +-
vendor/github.com/miekg/dns/smimea.go | 8 +-
vendor/github.com/miekg/dns/tsig.go | 3 +-
vendor/github.com/miekg/dns/types.go | 2 +-
vendor/github.com/miekg/dns/types_generate.go | 2 +-
vendor/github.com/miekg/dns/udp.go | 26 +-
vendor/github.com/miekg/dns/udp_linux.go | 25 +-
vendor/github.com/miekg/dns/udp_other.go | 6 +-
vendor/github.com/miekg/dns/udp_plan9.go | 34 -
vendor/github.com/miekg/dns/udp_windows.go | 9 +-
vendor/github.com/miekg/dns/update_test.go | 36 +-
vendor/github.com/miekg/dns/zcompress.go | 119 +
vendor/github.com/miekg/dns/ztypes.go | 58 +-
.../prometheus/client_model/AUTHORS.md | 13 -
.../prometheus/client_model/CONTRIBUTING.md | 8 +-
.../prometheus/client_model/MAINTAINERS.md | 1 +
.../github.com/prometheus/common/AUTHORS.md | 11 -
.../prometheus/common/CONTRIBUTING.md | 6 +-
.../prometheus/common/MAINTAINERS.md | 1 +
.../prometheus/common/model/value.go | 5 +-
.../prometheus/common/model/value_test.go | 53 +-
.../github.com/prometheus/procfs/AUTHORS.md | 21 -
.../prometheus/procfs/CONTRIBUTING.md | 6 +-
.../prometheus/procfs/MAINTAINERS.md | 1 +
vendor/github.com/prometheus/procfs/README.md | 1 +
.../github.com/prometheus/procfs/buddyinfo.go | 95 +
.../prometheus/procfs/buddyinfo_test.go | 64 +
.../procfs/fixtures/buddyinfo/short/buddyinfo | 3 +
.../fixtures/buddyinfo/sizemismatch/buddyinfo | 3 +
.../procfs/fixtures/buddyinfo/valid/buddyinfo | 3 +
.../prometheus/procfs/fixtures/fs/xfs/stat | 23 +
vendor/github.com/prometheus/procfs/fs.go | 13 +
.../github.com/prometheus/procfs/fs_test.go | 13 +
.../github.com/prometheus/procfs/ipvs_test.go | 16 +-
.../prometheus/procfs/mdstat_test.go | 14 +-
.../prometheus/procfs/mountstats.go | 4 +-
.../prometheus/procfs/mountstats_test.go | 9 +-
.../github.com/prometheus/procfs/xfs/parse.go | 361 +
.../prometheus/procfs/xfs/parse_test.go | 446 +
.../github.com/prometheus/procfs/xfs/xfs.go | 158 +
vendor/github.com/spf13/cobra/.travis.yml | 5 +-
vendor/github.com/spf13/cobra/README.md | 3 +-
vendor/github.com/spf13/cobra/command.go | 62 +-
vendor/github.com/spf13/cobra/doc/man_docs.go | 4 +-
vendor/github.com/spf13/cobra/doc/md_docs.go | 4 +-
vendor/github.com/spf13/cobra/doc/util.go | 2 +-
.../github.com/spf13/cobra/doc/yaml_docs.go | 4 +-
vendor/github.com/tylerb/graceful/README.md | 5 +
vendor/github.com/tylerb/graceful/graceful.go | 1 +
vendor/github.com/xenolf/lego/README.md | 6 +-
vendor/github.com/xenolf/lego/acme/client.go | 9 +
.../xenolf/lego/acme/client_test.go | 71 +
vendor/github.com/xenolf/lego/acme/error.go | 15 +-
vendor/github.com/xenolf/lego/acme/http.go | 10 +-
vendor/github.com/xenolf/lego/acme/jws.go | 105 +-
.../providers/http/memcached/memcached.go | 3 +-
vendor/golang.org/x/crypto/acme/acme.go | 119 +-
vendor/golang.org/x/crypto/acme/acme_test.go | 117 +-
.../x/crypto/acme/autocert/autocert_test.go | 41 +-
.../x/crypto/acme/autocert/renewal_test.go | 2 +-
.../x/crypto/blake2b/blake2bAVX2_amd64.s | 688 +-
.../golang.org/x/crypto/blake2b/register.go | 32 +
.../golang.org/x/crypto/blake2s/register.go | 21 +
vendor/golang.org/x/crypto/cryptobyte/asn1.go | 604 +
.../x/crypto/cryptobyte/asn1_test.go | 285 +
.../golang.org/x/crypto/cryptobyte/builder.go | 255 +
.../x/crypto/cryptobyte/cryptobyte_test.go | 379 +
.../x/crypto/cryptobyte/example_test.go | 120 +
.../golang.org/x/crypto/cryptobyte/string.go | 157 +
.../x/crypto/curve25519/const_amd64.h | 8 +
.../x/crypto/curve25519/const_amd64.s | 4 +-
.../x/crypto/curve25519/freeze_amd64.s | 4 +-
.../x/crypto/curve25519/ladderstep_amd64.s | 20 +-
.../x/crypto/curve25519/mul_amd64.s | 4 +-
.../x/crypto/curve25519/square_amd64.s | 4 +-
vendor/golang.org/x/crypto/ocsp/ocsp_test.go | 6 +-
.../x/crypto/poly1305/poly1305_test.go | 37 +
.../golang.org/x/crypto/poly1305/sum_ref.go | 1614 +-
.../x/crypto/ssh/agent/client_test.go | 2 +-
vendor/golang.org/x/crypto/ssh/cipher.go | 64 +-
vendor/golang.org/x/crypto/ssh/cipher_test.go | 62 +-
.../x/crypto/ssh/client_auth_test.go | 4 +-
vendor/golang.org/x/crypto/ssh/common.go | 2 +-
vendor/golang.org/x/crypto/ssh/handshake.go | 49 +-
.../golang.org/x/crypto/ssh/handshake_test.go | 61 +-
vendor/golang.org/x/crypto/ssh/mac.go | 10 +-
vendor/golang.org/x/crypto/ssh/mux_test.go | 3 +
vendor/golang.org/x/crypto/ssh/server.go | 27 +-
vendor/golang.org/x/crypto/ssh/transport.go | 32 +-
vendor/golang.org/x/image/draw/draw.go | 42 +-
vendor/golang.org/x/image/draw/gen.go | 2 +-
vendor/golang.org/x/image/draw/go1_8.go | 49 +
vendor/golang.org/x/image/draw/go1_9.go | 57 +
vendor/golang.org/x/image/draw/impl.go | 96 +-
vendor/golang.org/x/image/draw/stdlib_test.go | 6 +-
vendor/golang.org/x/image/font/sfnt/cmap.go | 269 +
vendor/golang.org/x/image/font/sfnt/data.go | 68 +
.../x/image/font/sfnt/example_test.go | 128 +
vendor/golang.org/x/image/font/sfnt/gen.go | 321 +
.../x/image/font/sfnt/postscript.go | 117 +-
.../x/image/font/sfnt/proprietary_test.go | 479 +
vendor/golang.org/x/image/font/sfnt/sfnt.go | 571 +-
.../golang.org/x/image/font/sfnt/sfnt_test.go | 370 +-
.../golang.org/x/image/font/sfnt/truetype.go | 29 +-
.../x/image/font/testdata/cmapTest.sfd | 265 +
.../x/image/font/testdata/cmapTest.ttf | Bin 0 -> 2528 bytes
.../x/image/testdata/go-turns-two-down-ab.png | Bin 21338 -> 21092 bytes
.../x/image/testdata/go-turns-two-down-bl.png | Bin 18581 -> 18169 bytes
.../x/image/testdata/go-turns-two-down-cr.png | Bin 19519 -> 19141 bytes
.../x/image/testdata/go-turns-two-down-nn.png | Bin 21504 -> 21320 bytes
.../image/testdata/go-turns-two-rotate-ab.png | Bin 7654 -> 7417 bytes
.../image/testdata/go-turns-two-rotate-bl.png | Bin 7653 -> 7421 bytes
.../image/testdata/go-turns-two-rotate-cr.png | Bin 7808 -> 7544 bytes
.../image/testdata/go-turns-two-rotate-nn.png | Bin 4915 -> 5128 bytes
.../x/image/testdata/go-turns-two-up-ab.png | Bin 9633 -> 9427 bytes
.../x/image/testdata/go-turns-two-up-bl.png | Bin 9639 -> 9427 bytes
.../x/image/testdata/go-turns-two-up-cr.png | Bin 10987 -> 10694 bytes
.../x/image/testdata/go-turns-two-up-nn.png | Bin 1368 -> 1369 bytes
.../x/image/testdata/tux-rotate-ab.png | Bin 3237 -> 3340 bytes
.../x/image/testdata/tux-rotate-bl.png | Bin 3751 -> 3836 bytes
.../x/image/testdata/tux-rotate-cr.png | Bin 3753 -> 3841 bytes
.../x/image/testdata/tux-rotate-nn.png | Bin 3055 -> 3159 bytes
vendor/golang.org/x/net/bpf/vm_bpf_test.go | 7 +-
vendor/golang.org/x/net/context/context.go | 30 +-
.../x/net/context/ctxhttp/ctxhttp_17_test.go | 1 +
vendor/golang.org/x/net/context/go17.go | 4 +-
vendor/golang.org/x/net/context/pre_go17.go | 18 +-
.../x/net/dns/dnsmessage/message.go | 1418 ++
.../x/net/dns/dnsmessage/message_test.go | 575 +
.../x/net/http2/client_conn_pool.go | 2 +-
vendor/golang.org/x/net/http2/databuffer.go | 146 +
.../golang.org/x/net/http2/databuffer_test.go | 155 +
vendor/golang.org/x/net/http2/fixed_buffer.go | 60 -
.../x/net/http2/fixed_buffer_test.go | 128 -
vendor/golang.org/x/net/http2/frame.go | 81 +-
vendor/golang.org/x/net/http2/frame_test.go | 91 +-
vendor/golang.org/x/net/http2/go18.go | 6 +-
vendor/golang.org/x/net/http2/go18_test.go | 13 +
vendor/golang.org/x/net/http2/hpack/encode.go | 29 +-
.../x/net/http2/hpack/encode_test.go | 70 +-
vendor/golang.org/x/net/http2/hpack/hpack.go | 104 +-
.../x/net/http2/hpack/hpack_test.go | 146 +-
vendor/golang.org/x/net/http2/hpack/tables.go | 250 +-
.../x/net/http2/hpack/tables_test.go | 188 +
vendor/golang.org/x/net/http2/pipe.go | 2 +-
vendor/golang.org/x/net/http2/server.go | 199 +-
vendor/golang.org/x/net/http2/server_test.go | 155 +-
vendor/golang.org/x/net/http2/transport.go | 9 +-
.../golang.org/x/net/http2/transport_test.go | 2 +-
.../x/net/internal/netreflect/socket.go | 4 +
.../x/net/internal/netreflect/socket_19.go | 37 +
.../x/net/internal/netreflect/socket_posix.go | 1 +
.../x/net/internal/netreflect/socket_stub.go | 1 +
.../x/net/internal/netreflect/socket_test.go | 3 +
.../x/net/internal/timeseries/timeseries.go | 2 +-
vendor/golang.org/x/net/ipv4/doc.go | 12 +-
vendor/golang.org/x/net/ipv4/endpoint.go | 8 +-
vendor/golang.org/x/net/ipv4/go19_test.go | 11 +
vendor/golang.org/x/net/ipv4/ipv4_test.go | 22 +
vendor/golang.org/x/net/ipv4/packet.go | 6 +-
vendor/golang.org/x/net/ipv4/payload_cmsg.go | 8 +-
.../golang.org/x/net/ipv4/payload_nocmsg.go | 8 +-
vendor/golang.org/x/net/ipv6/control.go | 2 +-
.../golang.org/x/net/ipv6/dgramopt_posix.go | 4 +-
vendor/golang.org/x/net/ipv6/dgramopt_stub.go | 4 +-
vendor/golang.org/x/net/ipv6/doc.go | 12 +-
vendor/golang.org/x/net/ipv6/endpoint.go | 4 +-
vendor/golang.org/x/net/ipv6/go19_test.go | 11 +
vendor/golang.org/x/net/ipv6/ipv6_test.go | 22 +
vendor/golang.org/x/net/ipv6/payload_cmsg.go | 8 +-
.../golang.org/x/net/ipv6/payload_nocmsg.go | 8 +-
vendor/golang.org/x/net/lif/address.go | 4 +-
vendor/golang.org/x/net/lif/binary.go | 49 +-
vendor/golang.org/x/net/lif/link.go | 12 +-
vendor/golang.org/x/net/lif/sys.go | 21 +
.../golang.org/x/net/lif/sys_solaris_amd64.s | 3 -
vendor/golang.org/x/net/lif/syscall.go | 5 -
vendor/golang.org/x/net/proxy/socks5.go | 59 +-
vendor/golang.org/x/net/publicsuffix/table.go | 17943 ++++++++--------
.../x/net/publicsuffix/table_test.go | 563 +-
vendor/golang.org/x/net/route/address.go | 152 +-
vendor/golang.org/x/net/route/binary.go | 2 +-
vendor/golang.org/x/net/route/defs_darwin.go | 8 +
.../golang.org/x/net/route/defs_dragonfly.go | 8 +
vendor/golang.org/x/net/route/defs_freebsd.go | 8 +
vendor/golang.org/x/net/route/defs_netbsd.go | 8 +
vendor/golang.org/x/net/route/defs_openbsd.go | 12 +
vendor/golang.org/x/net/route/message.go | 8 +-
vendor/golang.org/x/net/route/message_test.go | 129 +-
vendor/golang.org/x/net/route/route.go | 59 +-
.../golang.org/x/net/route/route_classic.go | 36 +
.../golang.org/x/net/route/route_openbsd.go | 35 +-
vendor/golang.org/x/net/route/sys.go | 7 +-
vendor/golang.org/x/net/route/sys_darwin.go | 45 +-
.../golang.org/x/net/route/sys_dragonfly.go | 39 +-
vendor/golang.org/x/net/route/sys_freebsd.go | 39 +-
vendor/golang.org/x/net/route/sys_netbsd.go | 34 +-
vendor/golang.org/x/net/route/sys_openbsd.go | 39 +-
vendor/golang.org/x/net/route/syscall.go | 5 -
vendor/golang.org/x/net/route/syscall.s | 8 -
vendor/golang.org/x/net/route/zsys_darwin.go | 6 +
.../golang.org/x/net/route/zsys_dragonfly.go | 6 +
.../x/net/route/zsys_freebsd_386.go | 6 +
.../x/net/route/zsys_freebsd_amd64.go | 6 +
.../x/net/route/zsys_freebsd_arm.go | 6 +
vendor/golang.org/x/net/route/zsys_netbsd.go | 6 +
vendor/golang.org/x/net/route/zsys_openbsd.go | 10 +
.../x/net/webdav/internal/xml/marshal.go | 8 +-
.../x/net/webdav/internal/xml/read.go | 8 +-
.../x/net/webdav/internal/xml/xml.go | 6 +-
vendor/golang.org/x/sys/unix/asm.s | 10 -
vendor/golang.org/x/sys/unix/mkall.sh | 4 +-
vendor/golang.org/x/sys/unix/mkerrors.sh | 18 +-
vendor/golang.org/x/sys/unix/mksyscall.pl | 25 +-
.../x/sys/unix/mksyscall_solaris.pl | 23 +-
.../golang.org/x/sys/unix/mksysnum_linux.pl | 12 +-
vendor/golang.org/x/sys/unix/syscall.go | 7 -
.../golang.org/x/sys/unix/syscall_darwin.go | 2 -
.../x/sys/unix/syscall_dragonfly.go | 1 -
.../golang.org/x/sys/unix/syscall_freebsd.go | 1 -
vendor/golang.org/x/sys/unix/syscall_linux.go | 150 +-
.../x/sys/unix/syscall_linux_mipsx.go | 2 -
.../x/sys/unix/syscall_linux_s390x.go | 1 -
.../golang.org/x/sys/unix/syscall_openbsd.go | 1 -
vendor/golang.org/x/sys/unix/types_linux.go | 8 +
.../x/sys/unix/zerrors_linux_386.go | 49 +
.../x/sys/unix/zerrors_linux_amd64.go | 56 +
.../x/sys/unix/zerrors_linux_arm.go | 53 +
.../x/sys/unix/zerrors_linux_arm64.go | 51 +
.../x/sys/unix/zerrors_linux_mips.go | 55 +
.../x/sys/unix/zerrors_linux_mips64.go | 48 +
.../x/sys/unix/zerrors_linux_mips64le.go | 48 +
.../x/sys/unix/zerrors_linux_mipsle.go | 46 +
.../x/sys/unix/zerrors_linux_ppc64.go | 51 +
.../x/sys/unix/zerrors_linux_ppc64le.go | 48 +
.../x/sys/unix/zerrors_linux_s390x.go | 47 +
.../x/sys/unix/zerrors_linux_sparc64.go | 46 +
.../x/sys/unix/zsyscall_darwin_386.go | 37 +-
.../x/sys/unix/zsyscall_darwin_amd64.go | 38 +-
.../x/sys/unix/zsyscall_darwin_arm.go | 51 +-
.../x/sys/unix/zsyscall_darwin_arm64.go | 37 +-
.../x/sys/unix/zsyscall_dragonfly_amd64.go | 35 +-
.../x/sys/unix/zsyscall_freebsd_386.go | 52 +-
.../x/sys/unix/zsyscall_freebsd_amd64.go | 52 +-
.../x/sys/unix/zsyscall_freebsd_arm.go | 52 +-
.../x/sys/unix/zsyscall_linux_386.go | 60 +-
.../x/sys/unix/zsyscall_linux_amd64.go | 61 +-
.../x/sys/unix/zsyscall_linux_arm.go | 59 +-
.../x/sys/unix/zsyscall_linux_arm64.go | 58 +-
.../x/sys/unix/zsyscall_linux_mips.go | 60 +-
.../x/sys/unix/zsyscall_linux_mips64.go | 61 +-
.../x/sys/unix/zsyscall_linux_mips64le.go | 61 +-
.../x/sys/unix/zsyscall_linux_mipsle.go | 60 +-
.../x/sys/unix/zsyscall_linux_ppc64.go | 61 +-
.../x/sys/unix/zsyscall_linux_ppc64le.go | 61 +-
.../x/sys/unix/zsyscall_linux_s390x.go | 61 +-
.../x/sys/unix/zsyscall_linux_sparc64.go | 61 +-
.../x/sys/unix/zsyscall_netbsd_386.go | 32 +-
.../x/sys/unix/zsyscall_netbsd_amd64.go | 32 +-
.../x/sys/unix/zsyscall_netbsd_arm.go | 32 +-
.../x/sys/unix/zsyscall_openbsd_386.go | 34 +-
.../x/sys/unix/zsyscall_openbsd_amd64.go | 34 +-
.../x/sys/unix/zsyscall_solaris_amd64.go | 41 +-
.../x/sys/unix/zsysnum_linux_386.go | 37 +-
.../x/sys/unix/zsysnum_linux_amd64.go | 22 +-
.../x/sys/unix/zsysnum_linux_arm.go | 35 +-
.../x/sys/unix/zsysnum_linux_arm64.go | 15 +-
.../x/sys/unix/zsysnum_linux_mips.go | 25 +-
.../x/sys/unix/zsysnum_linux_mips64.go | 9 +-
.../x/sys/unix/zsysnum_linux_mips64le.go | 9 +-
.../x/sys/unix/zsysnum_linux_mipsle.go | 25 +-
.../x/sys/unix/zsysnum_linux_ppc64.go | 11 +-
.../x/sys/unix/zsysnum_linux_ppc64le.go | 18 +-
.../x/sys/unix/zsysnum_linux_s390x.go | 5 +-
.../x/sys/unix/zsysnum_linux_sparc64.go | 2 +-
.../golang.org/x/sys/unix/ztypes_linux_386.go | 18 +
.../x/sys/unix/ztypes_linux_amd64.go | 18 +
.../golang.org/x/sys/unix/ztypes_linux_arm.go | 18 +
.../x/sys/unix/ztypes_linux_arm64.go | 18 +
.../x/sys/unix/ztypes_linux_mips.go | 18 +
.../x/sys/unix/ztypes_linux_mips64.go | 18 +
.../x/sys/unix/ztypes_linux_mips64le.go | 18 +
.../x/sys/unix/ztypes_linux_mipsle.go | 18 +
.../x/sys/unix/ztypes_linux_ppc64.go | 18 +
.../x/sys/unix/ztypes_linux_ppc64le.go | 18 +
.../x/sys/unix/ztypes_linux_s390x.go | 18 +
.../x/sys/unix/ztypes_linux_sparc64.go | 18 +
vendor/gopkg.in/gomail.v2/.travis.yml | 8 +
vendor/gopkg.in/gomail.v2/CHANGELOG.md | 20 +
vendor/gopkg.in/gomail.v2/CONTRIBUTING.md | 20 +
vendor/gopkg.in/gomail.v2/LICENSE | 20 +
vendor/gopkg.in/gomail.v2/README.md | 97 +
vendor/gopkg.in/gomail.v2/auth.go | 67 +
vendor/gopkg.in/gomail.v2/auth_test.go | 156 +
vendor/gopkg.in/gomail.v2/doc.go | 5 +
vendor/gopkg.in/gomail.v2/example_test.go | 215 +
vendor/gopkg.in/gomail.v2/message.go | 302 +
vendor/gopkg.in/gomail.v2/message_test.go | 630 +
vendor/gopkg.in/gomail.v2/mime.go | 19 +
vendor/gopkg.in/gomail.v2/mime_go14.go | 16 +
vendor/gopkg.in/gomail.v2/send.go | 117 +
vendor/gopkg.in/gomail.v2/send_test.go | 80 +
vendor/gopkg.in/gomail.v2/smtp.go | 175 +
vendor/gopkg.in/gomail.v2/smtp_test.go | 254 +
vendor/gopkg.in/gomail.v2/writeto.go | 242 +
vendor/gopkg.in/yaml.v2/scannerc.go | 2 +-
356 files changed, 26671 insertions(+), 14262 deletions(-)
create mode 100644 vendor/github.com/jaytaylor/html2text/.gitignore
create mode 100644 vendor/github.com/jaytaylor/html2text/.travis.yml
create mode 100644 vendor/github.com/jaytaylor/html2text/LICENSE
create mode 100644 vendor/github.com/jaytaylor/html2text/README.md
create mode 100644 vendor/github.com/jaytaylor/html2text/html2text.go
create mode 100644 vendor/github.com/jaytaylor/html2text/html2text_test.go
create mode 100755 vendor/github.com/jaytaylor/html2text/testdata/utf8.html
create mode 100755 vendor/github.com/jaytaylor/html2text/testdata/utf8_with_bom.xhtml
create mode 100644 vendor/github.com/miekg/dns/compress_generate.go
delete mode 100644 vendor/github.com/miekg/dns/udp_plan9.go
create mode 100644 vendor/github.com/miekg/dns/zcompress.go
delete mode 100644 vendor/github.com/prometheus/client_model/AUTHORS.md
create mode 100644 vendor/github.com/prometheus/client_model/MAINTAINERS.md
delete mode 100644 vendor/github.com/prometheus/common/AUTHORS.md
create mode 100644 vendor/github.com/prometheus/common/MAINTAINERS.md
delete mode 100644 vendor/github.com/prometheus/procfs/AUTHORS.md
create mode 100644 vendor/github.com/prometheus/procfs/MAINTAINERS.md
create mode 100644 vendor/github.com/prometheus/procfs/buddyinfo.go
create mode 100644 vendor/github.com/prometheus/procfs/buddyinfo_test.go
create mode 100644 vendor/github.com/prometheus/procfs/fixtures/buddyinfo/short/buddyinfo
create mode 100644 vendor/github.com/prometheus/procfs/fixtures/buddyinfo/sizemismatch/buddyinfo
create mode 100644 vendor/github.com/prometheus/procfs/fixtures/buddyinfo/valid/buddyinfo
create mode 100644 vendor/github.com/prometheus/procfs/fixtures/fs/xfs/stat
create mode 100644 vendor/github.com/prometheus/procfs/xfs/parse.go
create mode 100644 vendor/github.com/prometheus/procfs/xfs/parse_test.go
create mode 100644 vendor/github.com/prometheus/procfs/xfs/xfs.go
create mode 100644 vendor/golang.org/x/crypto/blake2b/register.go
create mode 100644 vendor/golang.org/x/crypto/blake2s/register.go
create mode 100644 vendor/golang.org/x/crypto/cryptobyte/asn1.go
create mode 100644 vendor/golang.org/x/crypto/cryptobyte/asn1_test.go
create mode 100644 vendor/golang.org/x/crypto/cryptobyte/builder.go
create mode 100644 vendor/golang.org/x/crypto/cryptobyte/cryptobyte_test.go
create mode 100644 vendor/golang.org/x/crypto/cryptobyte/example_test.go
create mode 100644 vendor/golang.org/x/crypto/cryptobyte/string.go
create mode 100644 vendor/golang.org/x/crypto/curve25519/const_amd64.h
create mode 100644 vendor/golang.org/x/image/draw/go1_8.go
create mode 100644 vendor/golang.org/x/image/draw/go1_9.go
create mode 100644 vendor/golang.org/x/image/font/sfnt/cmap.go
create mode 100644 vendor/golang.org/x/image/font/sfnt/data.go
create mode 100644 vendor/golang.org/x/image/font/sfnt/example_test.go
create mode 100644 vendor/golang.org/x/image/font/sfnt/gen.go
create mode 100644 vendor/golang.org/x/image/font/sfnt/proprietary_test.go
create mode 100644 vendor/golang.org/x/image/font/testdata/cmapTest.sfd
create mode 100644 vendor/golang.org/x/image/font/testdata/cmapTest.ttf
create mode 100644 vendor/golang.org/x/net/dns/dnsmessage/message.go
create mode 100644 vendor/golang.org/x/net/dns/dnsmessage/message_test.go
create mode 100644 vendor/golang.org/x/net/http2/databuffer.go
create mode 100644 vendor/golang.org/x/net/http2/databuffer_test.go
delete mode 100644 vendor/golang.org/x/net/http2/fixed_buffer.go
delete mode 100644 vendor/golang.org/x/net/http2/fixed_buffer_test.go
create mode 100644 vendor/golang.org/x/net/http2/hpack/tables_test.go
create mode 100644 vendor/golang.org/x/net/internal/netreflect/socket_19.go
create mode 100644 vendor/golang.org/x/net/ipv4/go19_test.go
create mode 100644 vendor/golang.org/x/net/ipv4/ipv4_test.go
create mode 100644 vendor/golang.org/x/net/ipv6/go19_test.go
create mode 100644 vendor/golang.org/x/net/ipv6/ipv6_test.go
create mode 100644 vendor/golang.org/x/net/lif/sys.go
delete mode 100644 vendor/golang.org/x/net/route/syscall.s
delete mode 100644 vendor/golang.org/x/sys/unix/asm.s
create mode 100644 vendor/gopkg.in/gomail.v2/.travis.yml
create mode 100644 vendor/gopkg.in/gomail.v2/CHANGELOG.md
create mode 100644 vendor/gopkg.in/gomail.v2/CONTRIBUTING.md
create mode 100644 vendor/gopkg.in/gomail.v2/LICENSE
create mode 100644 vendor/gopkg.in/gomail.v2/README.md
create mode 100644 vendor/gopkg.in/gomail.v2/auth.go
create mode 100644 vendor/gopkg.in/gomail.v2/auth_test.go
create mode 100644 vendor/gopkg.in/gomail.v2/doc.go
create mode 100644 vendor/gopkg.in/gomail.v2/example_test.go
create mode 100644 vendor/gopkg.in/gomail.v2/message.go
create mode 100644 vendor/gopkg.in/gomail.v2/message_test.go
create mode 100644 vendor/gopkg.in/gomail.v2/mime.go
create mode 100644 vendor/gopkg.in/gomail.v2/mime_go14.go
create mode 100644 vendor/gopkg.in/gomail.v2/send.go
create mode 100644 vendor/gopkg.in/gomail.v2/send_test.go
create mode 100644 vendor/gopkg.in/gomail.v2/smtp.go
create mode 100644 vendor/gopkg.in/gomail.v2/smtp_test.go
create mode 100644 vendor/gopkg.in/gomail.v2/writeto.go
diff --git a/glide.lock b/glide.lock
index edc45220e3..f84f12affd 100644
--- a/glide.lock
+++ b/glide.lock
@@ -1,5 +1,5 @@
-hash: 42839eb256dd5b5607d93cd50372cf55881de6e874a63525862ed3f0ac47682b
-updated: 2017-02-01T10:22:19.702548922-05:00
+hash: 978c0474f3432a26942e213ca1ba8e957fa5a34ee4652d736dae152fbd6d5384
+updated: 2017-03-13T11:12:52.056509274-04:00
imports:
- name: github.com/alecthomas/log4go
version: e5dc62318d9bd58682f1dceb53a4b24e8253682f
@@ -22,7 +22,7 @@ imports:
- name: github.com/go-sql-driver/mysql
version: a0583e0143b1624142adab07e0e97fe106d99561
- name: github.com/goamz/goamz
- version: b2c2eaf25cbb87f41087aa796facf82113809ed5
+ version: c35091c30f44b7f151ec9028b895465a191d1ea7
subpackages:
- aws
- s3
@@ -32,7 +32,7 @@ imports:
- raster
- truetype
- name: github.com/golang/protobuf
- version: 8ee79997227bf9b34611aee7946ae64735e6fd93
+ version: c9c7427a2a70d2eb3bafa0ab2dc163e45f143317
subpackages:
- proto
- name: github.com/gorilla/context
@@ -49,10 +49,12 @@ imports:
- simplelru
- name: github.com/inconshreveable/mousetrap
version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75
+- name: github.com/jaytaylor/html2text
+ version: f3b8a7ca0a23f0a806b2e1ad1247de39ecde54bf
- name: github.com/jehiah/go-strftime
version: 834e15c05a45371503440cc195bbd05c9a0968d9
- name: github.com/lib/pq
- version: a6657b2386e9b8be76484c08711b02c7cf867ead
+ version: e4af84aab01e159ca479940dbde304519e8e8811
subpackages:
- oid
- name: github.com/mattermost/rsc
@@ -66,7 +68,7 @@ imports:
subpackages:
- pbutil
- name: github.com/miekg/dns
- version: 99f84ae56e75126dd77e5de4fae2ea034a468ca1
+ version: c862b7e359850847d4945cce311db2ea90cab7c0
- name: github.com/minio/minio-go
version: 52cc94e879db78c2e2c6e160869df943137ec4cd
subpackages:
@@ -84,7 +86,7 @@ imports:
- i18n/language
- i18n/translation
- name: github.com/NYTimes/gziphandler
- version: 6710af535839f57c687b62c4c23d649f9545d885
+ version: fb3533722e14198abe471546c9798fd556531451
- name: github.com/pborman/uuid
version: a97ce2ca70fa5a848076093f05e639a89ca34d06
- name: github.com/prometheus/client_golang
@@ -92,15 +94,15 @@ imports:
subpackages:
- prometheus
- name: github.com/prometheus/client_model
- version: fa8ad6fec33561be4280a8f0514318c79d7f6cb6
+ version: 6f3806018612930941127f2a7c6c453ba2c527d2
subpackages:
- go
- name: github.com/prometheus/common
- version: dd2f054febf4a6c00f2343686efb775948a8bff4
+ version: 49fee292b27bfff7f354ee0f64e1bc4850462edf
subpackages:
- expfmt
- name: github.com/prometheus/procfs
- version: 1878d9fbb537119d24b21ca07effd591627cd160
+ version: a1dba9ce8baed984a2495b658c82687f8157b98f
- name: github.com/rsc/letsencrypt
version: 76104d26167d38b6a0010f42bfc8ec5487742e8b
- name: github.com/rwcarlsen/goexif
@@ -113,25 +115,25 @@ imports:
- name: github.com/segmentio/backo-go
version: 204274ad699c0983a70203a566887f17a717fef4
- name: github.com/spf13/cobra
- version: 35136c09d8da66b901337c6e86fd8e88a1a255bd
+ version: 16c014f1a19d865b765b420e74508f80eb831ada
- name: github.com/spf13/pflag
version: 9ff6c6923cfffbcd502984b8e0c80539a94968b7
- name: github.com/tylerb/graceful
- version: 0e9129e9c6d47da90dc0c188b26bd7bb1dab53cd
+ version: d72b0151351a13d0421b763b88f791469c4f5dc7
- name: github.com/xenolf/lego
- version: f5d538caab6dc0c167d4e32990c79bbf9eff578c
+ version: 6cac0ea7d8b28c889f709ec7fa92e92b82f490dd
subpackages:
- acme
- name: github.com/xtgo/uuid
version: a0b114877d4caeffbd7f87e3757c17fce570fea7
- name: golang.org/x/crypto
- version: dc137beb6cce2043eb6b5f223ab8bf51c32459f4
+ version: 728b753d0135da6801d45a38e6f43ff55779c5c2
subpackages:
- bcrypt
- blowfish
- ocsp
- name: golang.org/x/image
- version: 83686c547965220f8b5d75e83ddc67d73420a89f
+ version: 793f3be7dac93749dec06ae3fbe7d0ded4bdcf3d
subpackages:
- bmp
- font
@@ -139,14 +141,14 @@ imports:
- tiff
- tiff/lzw
- name: golang.org/x/net
- version: f2499483f923065a842d38eb4c7f1927e6fc6e6d
+ version: a6577fac2d73be281a500b310739095313165611
subpackages:
- context
- html
- html/atom
- publicsuffix
- name: golang.org/x/sys
- version: 7a6e5648d140666db5d920909e082ca00a87ba2c
+ version: 99f16d856c9836c42d24e7ab64ea72916925fa97
subpackages:
- unix
- name: golang.org/x/time
@@ -157,6 +159,8 @@ imports:
version: 4e86f4367175e39f69d9358a5f17b4dda270378d
- name: gopkg.in/fsnotify.v1
version: 629574ca2a5df945712d3079857300b5e4da0236
+- name: gopkg.in/gomail.v2
+ version: 41f3572897373c5538c50a2402db15db079fa4fd
- name: gopkg.in/square/go-jose.v1
version: aa2e30fdd1fe9dd3394119af66451ae790d50e0d
subpackages:
@@ -168,5 +172,5 @@ imports:
- store
- store/memstore
- name: gopkg.in/yaml.v2
- version: 4c78c975fe7c825c6d1466c42be594d1d6f3aba6
+ version: a3f3340b5840cee44f372bddb5880fcbc419b46a
testImports: []
diff --git a/glide.yaml b/glide.yaml
index 07b5be25e2..a3c317855a 100644
--- a/glide.yaml
+++ b/glide.yaml
@@ -4,6 +4,7 @@ import:
- package: github.com/alecthomas/log4go
- package: github.com/dgryski/dgoogauth
- package: github.com/disintegration/imaging
+ version: v1.0.0
- package: github.com/go-gorp/gorp
version: 0c9bc0918534d133cedb439a24adc7cbe66e4a9d
- package: github.com/go-ldap/ldap
@@ -79,3 +80,6 @@ import:
- package: github.com/dyatlov/go-opengraph
subpackages:
- opengraph
+- package: github.com/jaytaylor/html2text
+- package: gopkg.in/gomail.v2
+ version: 2.0.0
diff --git a/vendor/github.com/goamz/goamz/aws/aws.go b/vendor/github.com/goamz/goamz/aws/aws.go
index 49eed632e5..a4d3591603 100644
--- a/vendor/github.com/goamz/goamz/aws/aws.go
+++ b/vendor/github.com/goamz/goamz/aws/aws.go
@@ -71,6 +71,7 @@ var Regions = map[string]Region{
EUCentral.Name: EUCentral,
EUWest.Name: EUWest,
USEast.Name: USEast,
+ USEast2.Name: USEast2,
USWest.Name: USWest,
USWest2.Name: USWest2,
USGovWest.Name: USGovWest,
diff --git a/vendor/github.com/goamz/goamz/aws/regions.go b/vendor/github.com/goamz/goamz/aws/regions.go
index 94d79d46d9..c75d41e11e 100644
--- a/vendor/github.com/goamz/goamz/aws/regions.go
+++ b/vendor/github.com/goamz/goamz/aws/regions.go
@@ -46,6 +46,29 @@ var USEast = Region{
"https://streams.dynamodb.us-east-1.amazonaws.com",
}
+var USEast2 = Region{
+ "us-east-2",
+ "https://ec2.us-east-2.amazonaws.com",
+ "https://s3.amazonaws.com",
+ "",
+ true,
+ true,
+ "",
+ "",
+ "https://sns.us-east-2.amazonaws.com",
+ "https://sqs.us-east-2.amazonaws.com",
+ "https://iam.amazonaws.com",
+ "https://elasticloadbalancing.us-east-2.amazonaws.com",
+ "https://dynamodb.us-east-2.amazonaws.com",
+ ServiceInfo{"https://monitoring.us-east-2.amazonaws.com", V2Signature},
+ "https://autoscaling.us-east-1.amazonaws.com",
+ ServiceInfo{"https://rds.us-east-2.amazonaws.com", V2Signature},
+ "https://sts.amazonaws.com",
+ "https://cloudformation.us-east-2.amazonaws.com",
+ "https://ecs.us-east-2.amazonaws.com",
+ "https://streams.dynamodb.us-east-2.amazonaws.com",
+}
+
var USWest = Region{
"us-west-1",
"https://ec2.us-west-1.amazonaws.com",
diff --git a/vendor/github.com/goamz/goamz/sqs/sqs.go b/vendor/github.com/goamz/goamz/sqs/sqs.go
index 23f1951ab1..b54b698a80 100644
--- a/vendor/github.com/goamz/goamz/sqs/sqs.go
+++ b/vendor/github.com/goamz/goamz/sqs/sqs.go
@@ -48,6 +48,8 @@ func NewFrom(accessKey, secretKey, region string) (*SQS, error) {
switch region {
case "us.east", "us.east.1":
aws_region = aws.USEast
+ case "us.east.2":
+ aws_region = aws.USEast2
case "us.west", "us.west.1":
aws_region = aws.USWest
case "us.west.2":
diff --git a/vendor/github.com/golang/protobuf/descriptor/descriptor.go b/vendor/github.com/golang/protobuf/descriptor/descriptor.go
index 83607ff6c4..ac7e51bfb1 100644
--- a/vendor/github.com/golang/protobuf/descriptor/descriptor.go
+++ b/vendor/github.com/golang/protobuf/descriptor/descriptor.go
@@ -43,7 +43,7 @@ import (
"io/ioutil"
"github.com/golang/protobuf/proto"
- protobuf "google.golang.org/genproto/protobuf"
+ protobuf "github.com/golang/protobuf/protoc-gen-go/descriptor"
)
// extractFile extracts a FileDescriptorProto from a gzip'd buffer.
diff --git a/vendor/github.com/golang/protobuf/descriptor/descriptor_test.go b/vendor/github.com/golang/protobuf/descriptor/descriptor_test.go
index 282a1e3a77..27b0729cbe 100644
--- a/vendor/github.com/golang/protobuf/descriptor/descriptor_test.go
+++ b/vendor/github.com/golang/protobuf/descriptor/descriptor_test.go
@@ -6,7 +6,7 @@ import (
"github.com/golang/protobuf/descriptor"
tpb "github.com/golang/protobuf/proto/testdata"
- protobuf "google.golang.org/genproto/protobuf"
+ protobuf "github.com/golang/protobuf/protoc-gen-go/descriptor"
)
func TestMessage(t *testing.T) {
diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/Makefile b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/Makefile
index b1ac45c774..a0bf9fefd9 100644
--- a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/Makefile
+++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/Makefile
@@ -45,9 +45,9 @@ my_test/test.pb.go: my_test/test.proto
golden:
make -B my_test/test.pb.go
- sed -i '/return.*fileDescriptor/d' my_test/test.pb.go
- sed -i '/^var fileDescriptor/,/^}/d' my_test/test.pb.go
- sed -i '/proto.RegisterFile.*fileDescriptor/d' my_test/test.pb.go
+ sed -i -e '/return.*fileDescriptor/d' my_test/test.pb.go
+ sed -i -e '/^var fileDescriptor/,/^}/d' my_test/test.pb.go
+ sed -i -e '/proto.RegisterFile.*fileDescriptor/d' my_test/test.pb.go
gofmt -w my_test/test.pb.go
diff -w my_test/test.pb.go my_test/test.pb.go.golden
diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/my_test/test.pb.go b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/my_test/test.pb.go
index 9ec3e1292e..d8717d57d0 100644
--- a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/my_test/test.pb.go
+++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/my_test/test.pb.go
@@ -319,7 +319,7 @@ func (m *Reply) GetCompactKeys() []int32 {
type Reply_Entry struct {
KeyThatNeeds_1234Camel_CasIng *int64 `protobuf:"varint,1,req,name=key_that_needs_1234camel_CasIng,json=keyThatNeeds1234camelCasIng" json:"key_that_needs_1234camel_CasIng,omitempty"`
Value *int64 `protobuf:"varint,2,opt,name=value,def=7" json:"value,omitempty"`
- XMyFieldName_2 *int64 `protobuf:"varint,3,opt,name=_my_field_name_2,json=myFieldName2" json:"_my_field_name_2,omitempty"`
+ XMyFieldName_2 *int64 `protobuf:"varint,3,opt,name=_my_field_name_2,json=MyFieldName2" json:"_my_field_name_2,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
@@ -389,6 +389,7 @@ var E_ReplyExtensions_Time = &proto.ExtensionDesc{
Field: 101,
Name: "my.test.ReplyExtensions.time",
Tag: "fixed64,101,opt,name=time",
+ Filename: "my_test/test.proto",
}
var E_ReplyExtensions_Carrot = &proto.ExtensionDesc{
@@ -397,6 +398,7 @@ var E_ReplyExtensions_Carrot = &proto.ExtensionDesc{
Field: 105,
Name: "my.test.ReplyExtensions.carrot",
Tag: "bytes,105,opt,name=carrot",
+ Filename: "my_test/test.proto",
}
var E_ReplyExtensions_Donut = &proto.ExtensionDesc{
@@ -405,6 +407,7 @@ var E_ReplyExtensions_Donut = &proto.ExtensionDesc{
Field: 101,
Name: "my.test.ReplyExtensions.donut",
Tag: "bytes,101,opt,name=donut",
+ Filename: "my_test/test.proto",
}
type OtherReplyExtensions struct {
@@ -832,6 +835,7 @@ var E_Tag = &proto.ExtensionDesc{
Field: 103,
Name: "my.test.tag",
Tag: "bytes,103,opt,name=tag",
+ Filename: "my_test/test.proto",
}
var E_Donut = &proto.ExtensionDesc{
@@ -840,6 +844,7 @@ var E_Donut = &proto.ExtensionDesc{
Field: 106,
Name: "my.test.donut",
Tag: "bytes,106,opt,name=donut",
+ Filename: "my_test/test.proto",
}
func init() {
diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/my_test/test.pb.go.golden b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/my_test/test.pb.go.golden
index 9ec3e1292e..d8717d57d0 100644
--- a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/my_test/test.pb.go.golden
+++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/my_test/test.pb.go.golden
@@ -319,7 +319,7 @@ func (m *Reply) GetCompactKeys() []int32 {
type Reply_Entry struct {
KeyThatNeeds_1234Camel_CasIng *int64 `protobuf:"varint,1,req,name=key_that_needs_1234camel_CasIng,json=keyThatNeeds1234camelCasIng" json:"key_that_needs_1234camel_CasIng,omitempty"`
Value *int64 `protobuf:"varint,2,opt,name=value,def=7" json:"value,omitempty"`
- XMyFieldName_2 *int64 `protobuf:"varint,3,opt,name=_my_field_name_2,json=myFieldName2" json:"_my_field_name_2,omitempty"`
+ XMyFieldName_2 *int64 `protobuf:"varint,3,opt,name=_my_field_name_2,json=MyFieldName2" json:"_my_field_name_2,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
@@ -389,6 +389,7 @@ var E_ReplyExtensions_Time = &proto.ExtensionDesc{
Field: 101,
Name: "my.test.ReplyExtensions.time",
Tag: "fixed64,101,opt,name=time",
+ Filename: "my_test/test.proto",
}
var E_ReplyExtensions_Carrot = &proto.ExtensionDesc{
@@ -397,6 +398,7 @@ var E_ReplyExtensions_Carrot = &proto.ExtensionDesc{
Field: 105,
Name: "my.test.ReplyExtensions.carrot",
Tag: "bytes,105,opt,name=carrot",
+ Filename: "my_test/test.proto",
}
var E_ReplyExtensions_Donut = &proto.ExtensionDesc{
@@ -405,6 +407,7 @@ var E_ReplyExtensions_Donut = &proto.ExtensionDesc{
Field: 101,
Name: "my.test.ReplyExtensions.donut",
Tag: "bytes,101,opt,name=donut",
+ Filename: "my_test/test.proto",
}
type OtherReplyExtensions struct {
@@ -832,6 +835,7 @@ var E_Tag = &proto.ExtensionDesc{
Field: 103,
Name: "my.test.tag",
Tag: "bytes,103,opt,name=tag",
+ Filename: "my_test/test.proto",
}
var E_Donut = &proto.ExtensionDesc{
@@ -840,6 +844,7 @@ var E_Donut = &proto.ExtensionDesc{
Field: 106,
Name: "my.test.donut",
Tag: "bytes,106,opt,name=donut",
+ Filename: "my_test/test.proto",
}
func init() {
diff --git a/vendor/github.com/jaytaylor/html2text/.gitignore b/vendor/github.com/jaytaylor/html2text/.gitignore
new file mode 100644
index 0000000000..daf913b1b3
--- /dev/null
+++ b/vendor/github.com/jaytaylor/html2text/.gitignore
@@ -0,0 +1,24 @@
+# Compiled Object files, Static and Dynamic libs (Shared Objects)
+*.o
+*.a
+*.so
+
+# Folders
+_obj
+_test
+
+# Architecture specific extensions/prefixes
+*.[568vq]
+[568vq].out
+
+*.cgo1.go
+*.cgo2.c
+_cgo_defun.c
+_cgo_gotypes.go
+_cgo_export.*
+
+_testmain.go
+
+*.exe
+*.test
+*.prof
diff --git a/vendor/github.com/jaytaylor/html2text/.travis.yml b/vendor/github.com/jaytaylor/html2text/.travis.yml
new file mode 100644
index 0000000000..6c7f48efd4
--- /dev/null
+++ b/vendor/github.com/jaytaylor/html2text/.travis.yml
@@ -0,0 +1,14 @@
+language: go
+go:
+ - tip
+ - 1.8
+ - 1.7
+ - 1.6
+ - 1.5
+ - 1.4
+ - 1.3
+ - 1.2
+notifications:
+ email:
+ on_success: change
+ on_failure: always
diff --git a/vendor/github.com/jaytaylor/html2text/LICENSE b/vendor/github.com/jaytaylor/html2text/LICENSE
new file mode 100644
index 0000000000..24dc4abecc
--- /dev/null
+++ b/vendor/github.com/jaytaylor/html2text/LICENSE
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Jay Taylor
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
diff --git a/vendor/github.com/jaytaylor/html2text/README.md b/vendor/github.com/jaytaylor/html2text/README.md
new file mode 100644
index 0000000000..ac11247393
--- /dev/null
+++ b/vendor/github.com/jaytaylor/html2text/README.md
@@ -0,0 +1,116 @@
+# html2text
+
+[](https://godoc.org/github.com/jaytaylor/html2text)
+[](https://travis-ci.org/jaytaylor/html2text)
+[](https://goreportcard.com/report/github.com/jaytaylor/html2text)
+
+### Converts HTML into text
+
+
+## Introduction
+
+Ensure your emails are readable by all!
+
+Turns HTML into raw text, useful for sending fancy HTML emails with a equivalently nicely formatted TXT document as a fallback (e.g. for people who don't allow HTML emails or have other display issues).
+
+html2text is a simple golang package for rendering HTML into plaintext.
+
+There are still lots of improvements to be had, but FWIW this has worked fine for my [basic] HTML-2-text needs.
+
+It requires go 1.x or newer ;)
+
+
+## Download the package
+
+```bash
+go get github.com/jaytaylor/html2text
+```
+
+## Example usage
+
+```go
+package main
+
+import (
+ "fmt"
+
+ "github.com/jaytaylor/html2text"
+)
+
+func main() {
+ inputHtml := `
+
+
+ My Mega Service
+
+
+
+
+
+
+
+
+
+ Welcome to your new account on my service!
+
+
+ Here is some more information:
+
+
+
+
+
+ `
+
+ text, err := html2text.FromString(inputHtml)
+ if err != nil {
+ panic(err)
+ }
+ fmt.Println(text)
+}
+```
+
+Output:
+```
+Mega Service ( http://mymegaservice.com/ )
+
+******************************************
+Welcome to your new account on my service!
+******************************************
+
+Here is some more information:
+
+* Link 1: Example.com ( https://example.com )
+* Link 2: Example2.com ( https://example2.com )
+* Something else
+```
+
+
+## Unit-tests
+
+Running the unit-tests is straightforward and standard:
+
+```bash
+go test
+```
+
+
+# License
+
+Permissive MIT license.
+
+
+## Contact
+
+You are more than welcome to open issues and send pull requests if you find a bug or want a new feature.
+
+If you appreciate this library please feel free to drop me a line and tell me! It's always nice to hear from people who have benefitted from my work.
+
+Email: jay at (my github username).com
+
+Twitter: [@jtaylor](https://twitter.com/jtaylor)
+
diff --git a/vendor/github.com/jaytaylor/html2text/html2text.go b/vendor/github.com/jaytaylor/html2text/html2text.go
new file mode 100644
index 0000000000..2a013a0395
--- /dev/null
+++ b/vendor/github.com/jaytaylor/html2text/html2text.go
@@ -0,0 +1,312 @@
+package html2text
+
+import (
+ "bytes"
+ "io"
+ "regexp"
+ "strings"
+ "unicode"
+
+ "github.com/ssor/bom"
+
+ "golang.org/x/net/html"
+ "golang.org/x/net/html/atom"
+)
+
+var (
+ spacingRe = regexp.MustCompile(`[ \r\n\t]+`)
+ newlineRe = regexp.MustCompile(`\n\n+`)
+)
+
+type textifyTraverseCtx struct {
+ Buf bytes.Buffer
+
+ prefix string
+ blockquoteLevel int
+ lineLength int
+ endsWithSpace bool
+ endsWithNewline bool
+ justClosedDiv bool
+}
+
+func (ctx *textifyTraverseCtx) traverse(node *html.Node) error {
+ switch node.Type {
+ default:
+ return ctx.traverseChildren(node)
+
+ case html.TextNode:
+ data := strings.Trim(spacingRe.ReplaceAllString(node.Data, " "), " ")
+ return ctx.emit(data)
+
+ case html.ElementNode:
+ return ctx.handleElementNode(node)
+ }
+}
+
+func (ctx *textifyTraverseCtx) handleElementNode(node *html.Node) error {
+ ctx.justClosedDiv = false
+ switch node.DataAtom {
+ case atom.Br:
+ return ctx.emit("\n")
+
+ case atom.H1, atom.H2, atom.H3:
+ subCtx := textifyTraverseCtx{}
+ if err := subCtx.traverseChildren(node); err != nil {
+ return err
+ }
+
+ str := subCtx.Buf.String()
+ dividerLen := 0
+ for _, line := range strings.Split(str, "\n") {
+ if lineLen := len([]rune(line)); lineLen-1 > dividerLen {
+ dividerLen = lineLen - 1
+ }
+ }
+ divider := ""
+ if node.DataAtom == atom.H1 {
+ divider = strings.Repeat("*", dividerLen)
+ } else {
+ divider = strings.Repeat("-", dividerLen)
+ }
+
+ if node.DataAtom == atom.H3 {
+ return ctx.emit("\n\n" + str + "\n" + divider + "\n\n")
+ }
+ return ctx.emit("\n\n" + divider + "\n" + str + "\n" + divider + "\n\n")
+
+ case atom.Blockquote:
+ ctx.blockquoteLevel++
+ ctx.prefix = strings.Repeat(">", ctx.blockquoteLevel) + " "
+ if err := ctx.emit("\n"); err != nil {
+ return err
+ }
+ if ctx.blockquoteLevel == 1 {
+ if err := ctx.emit("\n"); err != nil {
+ return err
+ }
+ }
+ if err := ctx.traverseChildren(node); err != nil {
+ return err
+ }
+ ctx.blockquoteLevel--
+ ctx.prefix = strings.Repeat(">", ctx.blockquoteLevel)
+ if ctx.blockquoteLevel > 0 {
+ ctx.prefix += " "
+ }
+ return ctx.emit("\n\n")
+
+ case atom.Div:
+ if ctx.lineLength > 0 {
+ if err := ctx.emit("\n"); err != nil {
+ return err
+ }
+ }
+ if err := ctx.traverseChildren(node); err != nil {
+ return err
+ }
+ var err error
+ if ctx.justClosedDiv == false {
+ err = ctx.emit("\n")
+ }
+ ctx.justClosedDiv = true
+ return err
+
+ case atom.Li:
+ if err := ctx.emit("* "); err != nil {
+ return err
+ }
+
+ if err := ctx.traverseChildren(node); err != nil {
+ return err
+ }
+
+ return ctx.emit("\n")
+
+ case atom.B, atom.Strong:
+ subCtx := textifyTraverseCtx{}
+ subCtx.endsWithSpace = true
+ if err := subCtx.traverseChildren(node); err != nil {
+ return err
+ }
+ str := subCtx.Buf.String()
+ return ctx.emit("*" + str + "*")
+
+ case atom.A:
+ // If image is the only child, take its alt text as the link text
+ if img := node.FirstChild; img != nil && node.LastChild == img && img.DataAtom == atom.Img {
+ if altText := getAttrVal(img, "alt"); altText != "" {
+ ctx.emit(altText)
+ }
+ } else if err := ctx.traverseChildren(node); err != nil {
+ return err
+ }
+
+ hrefLink := ""
+ if attrVal := getAttrVal(node, "href"); attrVal != "" {
+ attrVal = ctx.normalizeHrefLink(attrVal)
+ if attrVal != "" {
+ hrefLink = "( " + attrVal + " )"
+ }
+ }
+
+ return ctx.emit(hrefLink)
+
+ case atom.P, atom.Ul, atom.Table:
+ if err := ctx.emit("\n\n"); err != nil {
+ return err
+ }
+
+ if err := ctx.traverseChildren(node); err != nil {
+ return err
+ }
+
+ return ctx.emit("\n\n")
+
+ case atom.Tr:
+ if err := ctx.traverseChildren(node); err != nil {
+ return err
+ }
+
+ return ctx.emit("\n")
+
+ case atom.Style, atom.Script, atom.Head:
+ // Ignore the subtree
+ return nil
+
+ default:
+ return ctx.traverseChildren(node)
+ }
+}
+func (ctx *textifyTraverseCtx) traverseChildren(node *html.Node) error {
+ for c := node.FirstChild; c != nil; c = c.NextSibling {
+ if err := ctx.traverse(c); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func (ctx *textifyTraverseCtx) emit(data string) error {
+ if len(data) == 0 {
+ return nil
+ }
+ lines := ctx.breakLongLines(data)
+ var err error
+ for _, line := range lines {
+ runes := []rune(line)
+ startsWithSpace := unicode.IsSpace(runes[0])
+ if !startsWithSpace && !ctx.endsWithSpace {
+ ctx.Buf.WriteByte(' ')
+ ctx.lineLength++
+ }
+ ctx.endsWithSpace = unicode.IsSpace(runes[len(runes)-1])
+ for _, c := range line {
+ _, err = ctx.Buf.WriteString(string(c))
+ if err != nil {
+ return err
+ }
+ ctx.lineLength++
+ if c == '\n' {
+ ctx.lineLength = 0
+ if ctx.prefix != "" {
+ _, err = ctx.Buf.WriteString(ctx.prefix)
+ if err != nil {
+ return err
+ }
+ }
+ }
+ }
+ }
+ return nil
+}
+
+func (ctx *textifyTraverseCtx) breakLongLines(data string) []string {
+ // only break lines when we are in blockquotes
+ if ctx.blockquoteLevel == 0 {
+ return []string{data}
+ }
+ var ret []string
+ runes := []rune(data)
+ l := len(runes)
+ existing := ctx.lineLength
+ if existing >= 74 {
+ ret = append(ret, "\n")
+ existing = 0
+ }
+ for l+existing > 74 {
+ i := 74 - existing
+ for i >= 0 && !unicode.IsSpace(runes[i]) {
+ i--
+ }
+ if i == -1 {
+ // no spaces, so go the other way
+ i = 74 - existing
+ for i < l && !unicode.IsSpace(runes[i]) {
+ i++
+ }
+ }
+ ret = append(ret, string(runes[:i])+"\n")
+ for i < l && unicode.IsSpace(runes[i]) {
+ i++
+ }
+ runes = runes[i:]
+ l = len(runes)
+ existing = 0
+ }
+ if len(runes) > 0 {
+ ret = append(ret, string(runes))
+ }
+ return ret
+}
+
+func (ctx *textifyTraverseCtx) normalizeHrefLink(link string) string {
+ link = strings.TrimSpace(link)
+ link = strings.TrimPrefix(link, "mailto:")
+ return link
+}
+
+func getAttrVal(node *html.Node, attrName string) string {
+ for _, attr := range node.Attr {
+ if attr.Key == attrName {
+ return attr.Val
+ }
+ }
+
+ return ""
+}
+
+func FromHtmlNode(doc *html.Node) (string, error) {
+ ctx := textifyTraverseCtx{
+ Buf: bytes.Buffer{},
+ }
+ if err := ctx.traverse(doc); err != nil {
+ return "", err
+ }
+
+ text := strings.TrimSpace(newlineRe.ReplaceAllString(
+ strings.Replace(ctx.Buf.String(), "\n ", "\n", -1), "\n\n"))
+ return text, nil
+
+}
+
+func FromReader(reader io.Reader) (string, error) {
+ newReader, err := bom.NewReaderWithoutBom(reader)
+ if err != nil {
+ return "", err
+ }
+ doc, err := html.Parse(newReader)
+ if err != nil {
+ return "", err
+ }
+ return FromHtmlNode(doc)
+}
+
+func FromString(input string) (string, error) {
+ bs := bom.CleanBom([]byte(input))
+ text, err := FromReader(bytes.NewReader(bs))
+ if err != nil {
+ return "", err
+ }
+ return text, nil
+}
diff --git a/vendor/github.com/jaytaylor/html2text/html2text_test.go b/vendor/github.com/jaytaylor/html2text/html2text_test.go
new file mode 100644
index 0000000000..b30d68ac97
--- /dev/null
+++ b/vendor/github.com/jaytaylor/html2text/html2text_test.go
@@ -0,0 +1,674 @@
+package html2text
+
+import (
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "path"
+ "regexp"
+ "strings"
+ "testing"
+)
+
+const (
+ destPath = "testdata"
+)
+
+func TestParseUTF8(t *testing.T) {
+ htmlFiles := []struct {
+ file string
+ keywordShouldNotExist string
+ keywordShouldExist string
+ }{
+ {
+ "utf8.html",
+ "学习之道:美国公认学习第一书title",
+ "次世界冠军赛上,我几近疯狂",
+ },
+ {
+ "utf8_with_bom.xhtml",
+ "1892年波兰文版序言title",
+ "种新的波兰文本已成为必要",
+ },
+ }
+
+ for _, htmlFile := range htmlFiles {
+ bs, err := ioutil.ReadFile(path.Join(destPath, htmlFile.file))
+ if err != nil {
+ t.Fatal(err)
+ }
+ text, err := FromReader(bytes.NewReader(bs))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !strings.Contains(text, htmlFile.keywordShouldExist) {
+ t.Fatalf("keyword %s should exists in file %s", htmlFile.keywordShouldExist, htmlFile.file)
+ }
+ if strings.Contains(text, htmlFile.keywordShouldNotExist) {
+ t.Fatalf("keyword %s should not exists in file %s", htmlFile.keywordShouldNotExist, htmlFile.file)
+ }
+ }
+}
+
+func TestStrippingWhitespace(t *testing.T) {
+ testCases := []struct {
+ input string
+ output string
+ }{
+ {
+ "test text",
+ "test text",
+ },
+ {
+ " \ttext\ntext\n",
+ "text text",
+ },
+ {
+ " \na \n\t \n \n a \t",
+ "a a",
+ },
+ {
+ "test text",
+ "test text",
+ },
+ {
+ "test text ",
+ "test text",
+ },
+ }
+
+ for _, testCase := range testCases {
+ assertString(t, testCase.input, testCase.output)
+ }
+}
+
+func TestParagraphsAndBreaks(t *testing.T) {
+ testCases := []struct {
+ input string
+ output string
+ }{
+ {
+ "Test text",
+ "Test text",
+ },
+ {
+ "Test text ",
+ "Test text",
+ },
+ {
+ "Test text Test",
+ "Test text\nTest",
+ },
+ {
+ "Test text
",
+ "Test text",
+ },
+ {
+ "Test text
Test text
",
+ "Test text\n\nTest text",
+ },
+ {
+ "\nTest text
\n\n\n\tTest text
\n",
+ "Test text\n\nTest text",
+ },
+ {
+ "\nTest text Test text
\n",
+ "Test text\nTest text",
+ },
+ {
+ "\nTest text \tTest text
\n",
+ "Test text\nTest text",
+ },
+ {
+ "Test text Test text",
+ "Test text\n\nTest text",
+ },
+ }
+
+ for _, testCase := range testCases {
+ assertString(t, testCase.input, testCase.output)
+ }
+}
+
+func TestTables(t *testing.T) {
+ testCases := []struct {
+ input string
+ output string
+ }{
+ {
+ "",
+ "",
+ },
+ {
+ "",
+ "cell1 cell2",
+ },
+ {
+ "",
+ "row1\nrow2",
+ },
+ {
+ `
+ cell1-1 cell1-2
+ cell2-1 cell2-2
+
`,
+ "cell1-1 cell1-2\ncell2-1 cell2-2",
+ },
+ {
+ "__",
+ "_\n\ncell\n\n_",
+ },
+ }
+
+ for _, testCase := range testCases {
+ assertString(t, testCase.input, testCase.output)
+ }
+}
+
+func TestStrippingLists(t *testing.T) {
+ testCases := []struct {
+ input string
+ output string
+ }{
+ {
+ "",
+ "",
+ },
+ {
+ "_",
+ "* item\n\n_",
+ },
+ {
+ "item 1 item 2 \n_",
+ "* item 1\n* item 2\n_",
+ },
+ {
+ "item 1 \t\n item 2 item 3 \n_",
+ "* item 1\n* item 2\n* item 3\n_",
+ },
+ }
+
+ for _, testCase := range testCases {
+ assertString(t, testCase.input, testCase.output)
+ }
+}
+
+func TestLinks(t *testing.T) {
+ testCases := []struct {
+ input string
+ output string
+ }{
+ {
+ ` `,
+ ``,
+ },
+ {
+ ` `,
+ ``,
+ },
+ {
+ ` `,
+ `( http://example.com/ )`,
+ },
+ {
+ `Link `,
+ `Link`,
+ },
+ {
+ `Link `,
+ `Link ( http://example.com/ )`,
+ },
+ {
+ `Link `,
+ `Link ( http://example.com/ )`,
+ },
+ {
+ "\n\tLink \n\t ",
+ `Link ( http://example.com/ )`,
+ },
+ {
+ "Contact Us ",
+ `Contact Us ( contact@example.org )`,
+ },
+ {
+ "Link ",
+ `Link ( http://example.com:80/~user?aaa=bb&c=d,e,f#foo )`,
+ },
+ {
+ "Link ",
+ `Link ( http://example.com/ )`,
+ },
+ {
+ " Link ",
+ `Link ( http://example.com/ )`,
+ },
+ {
+ "Link A Link B ",
+ `Link A ( http://example.com/a/ ) Link B ( http://example.com/b/ )`,
+ },
+ {
+ "Link ",
+ `Link ( %%LINK%% )`,
+ },
+ {
+ "Link ",
+ `Link ( [LINK] )`,
+ },
+ {
+ "Link ",
+ `Link ( {LINK} )`,
+ },
+ {
+ "Link ",
+ `Link ( [[!unsubscribe]] )`,
+ },
+ {
+ "This is link1 and link2 is next.
",
+ `This is link1 ( http://www.google.com ) and link2 ( http://www.google.com ) is next.`,
+ },
+ }
+
+ for _, testCase := range testCases {
+ assertString(t, testCase.input, testCase.output)
+ }
+}
+
+func TestImageAltTags(t *testing.T) {
+ testCases := []struct {
+ input string
+ output string
+ }{
+ {
+ ` `,
+ ``,
+ },
+ {
+ ` `,
+ ``,
+ },
+ {
+ ` `,
+ ``,
+ },
+ {
+ ` `,
+ ``,
+ },
+ // Images do matter if they are in a link
+ {
+ ` `,
+ `Example ( http://example.com/ )`,
+ },
+ {
+ ` `,
+ `Example ( http://example.com/ )`,
+ },
+ {
+ ` `,
+ `Example ( http://example.com/ )`,
+ },
+ {
+ ` `,
+ `Example ( http://example.com/ )`,
+ },
+ }
+
+ for _, testCase := range testCases {
+ assertString(t, testCase.input, testCase.output)
+ }
+}
+
+func TestHeadings(t *testing.T) {
+ testCases := []struct {
+ input string
+ output string
+ }{
+ {
+ "Test ",
+ "****\nTest\n****",
+ },
+ {
+ "\t\nTest ",
+ "****\nTest\n****",
+ },
+ {
+ "\t\nTest line 1 Test 2 ",
+ "***********\nTest line 1\nTest 2\n***********",
+ },
+ {
+ "Test Test ",
+ "****\nTest\n****\n\n****\nTest\n****",
+ },
+ {
+ "Test ",
+ "----\nTest\n----",
+ },
+ {
+ "",
+ "****************************\nTest ( http://example.com/ )\n****************************",
+ },
+ {
+ " Test ",
+ "Test\n----",
+ },
+ }
+
+ for _, testCase := range testCases {
+ assertString(t, testCase.input, testCase.output)
+ }
+
+}
+
+func TestBold(t *testing.T) {
+ testCases := []struct {
+ input string
+ output string
+ }{
+ {
+ "Test ",
+ "*Test*",
+ },
+ {
+ "\tTest ",
+ "*Test*",
+ },
+ {
+ "\tTest line 1 Test 2 ",
+ "*Test line 1\nTest 2*",
+ },
+ {
+ "Test Test ",
+ "*Test* *Test*",
+ },
+ }
+
+ for _, testCase := range testCases {
+ assertString(t, testCase.input, testCase.output)
+ }
+
+}
+
+func TestDiv(t *testing.T) {
+ testCases := []struct {
+ input string
+ output string
+ }{
+ {
+ "Test
",
+ "Test",
+ },
+ {
+ "\tTest
",
+ "Test",
+ },
+ {
+ "",
+ "Test line 1\nTest 2",
+ },
+ {
+ "Test 1Test 2
Test 3
Test 4",
+ "Test 1\nTest 2\nTest 3\nTest 4",
+ },
+ }
+
+ for _, testCase := range testCases {
+ assertString(t, testCase.input, testCase.output)
+ }
+
+}
+
+func TestBlockquotes(t *testing.T) {
+ testCases := []struct {
+ input string
+ output string
+ }{
+ {
+ "level 0
level 1level 2 level 1 level 0
",
+ "level 0\n> \n> level 1\n> \n>> level 2\n> \n> level 1\n\nlevel 0",
+ },
+ {
+ "Test Test",
+ "> \n> Test\n\nTest",
+ },
+ {
+ "\t \nTest ",
+ "> \n> Test\n>",
+ },
+ {
+ "\t \nTest line 1 Test 2 ",
+ "> \n> Test line 1\n> Test 2",
+ },
+ {
+ "Test Test Other Test",
+ "> \n> Test\n\n> \n> Test\n\nOther Test",
+ },
+ {
+ "Lorem ipsum Commodo id consectetur pariatur ea occaecat minim aliqua ad sit consequat quis ex commodo Duis incididunt eu mollit consectetur fugiat voluptate dolore in pariatur in commodo occaecat Ut occaecat velit esse labore aute quis commodo non sit dolore officia Excepteur cillum amet cupidatat culpa velit labore ullamco dolore mollit elit in aliqua dolor irure do ",
+ "> \n> Lorem ipsum Commodo id consectetur pariatur ea occaecat minim aliqua ad\n> sit consequat quis ex commodo Duis incididunt eu mollit consectetur fugiat\n> voluptate dolore in pariatur in commodo occaecat Ut occaecat velit esse\n> labore aute quis commodo non sit dolore officia Excepteur cillum amet\n> cupidatat culpa velit labore ullamco dolore mollit elit in aliqua dolor\n> irure do",
+ },
+ {
+ "Loremipsum Commodo id consectetur pariatur ea occaecat minim aliqua ad sit consequat quis ex commodo Duis incididunt eu mollit consectetur fugiat voluptate dolore in pariatur in commodo occaecat Ut occaecat velit esse labore aute quis commodo non sit dolore officia Excepteur cillum amet cupidatat culpa velit labore ullamco dolore mollit elit in aliqua dolor irure do ",
+ "> \n> Lorem *ipsum* *Commodo* *id* *consectetur* *pariatur* *ea* *occaecat* *minim*\n> *aliqua* *ad* *sit* *consequat* *quis* *ex* *commodo* *Duis* *incididunt* *eu*\n> *mollit* *consectetur* *fugiat* *voluptate* *dolore* *in* *pariatur* *in* *commodo*\n> *occaecat* *Ut* *occaecat* *velit* *esse* *labore* *aute* *quis* *commodo*\n> *non* *sit* *dolore* *officia* *Excepteur* *cillum* *amet* *cupidatat* *culpa*\n> *velit* *labore* *ullamco* *dolore* *mollit* *elit* *in* *aliqua* *dolor* *irure*\n> *do*",
+ },
+ }
+
+ for _, testCase := range testCases {
+ assertString(t, testCase.input, testCase.output)
+ }
+
+}
+
+func TestIgnoreStylesScriptsHead(t *testing.T) {
+ testCases := []struct {
+ input string
+ output string
+ }{
+ {
+ "",
+ "",
+ },
+ {
+ "",
+ "",
+ },
+ {
+ " ",
+ "",
+ },
+ {
+ "",
+ "",
+ },
+ {
+ "",
+ "",
+ },
+ {
+ "",
+ "",
+ },
+ {
+ "",
+ "",
+ },
+ {
+ "",
+ "",
+ },
+ {
+ "",
+ "",
+ },
+ {
+ `Title `,
+ "",
+ },
+ }
+
+ for _, testCase := range testCases {
+ assertString(t, testCase.input, testCase.output)
+ }
+}
+
+func TestText(t *testing.T) {
+ testCases := []struct {
+ input string
+ expr string
+ }{
+ {
+ `
+ New repository
+ `,
+ `\* New repository \( /new \)`,
+ },
+ {
+ `hi
+
+
+
+ hello google
+
+ testList:
+
+
+`,
+ `hi
+hello google \( https://google.com \)
+
+test
+
+List:
+
+\* Foo \( foo \)
+\* Barsoap \( http://www.microshwhat.com/bar/soapy \)
+\* Baz`,
+ },
+ // Malformed input html.
+ {
+ `hi
+
+ hello google
+
+ testList:
+
+
+ `,
+ `hi hello google \( https://google.com \) test
+
+List:
+
+\* Foo \( foo \)
+\* Bar \( /\n[ \t]+bar/baz \)
+\* Baz`,
+ },
+ }
+
+ for _, testCase := range testCases {
+ assertRegexp(t, testCase.input, testCase.expr)
+ }
+}
+
+type StringMatcher interface {
+ MatchString(string) bool
+ String() string
+}
+
+type RegexpStringMatcher string
+
+func (m RegexpStringMatcher) MatchString(str string) bool {
+ return regexp.MustCompile(string(m)).MatchString(str)
+}
+func (m RegexpStringMatcher) String() string {
+ return string(m)
+}
+
+type ExactStringMatcher string
+
+func (m ExactStringMatcher) MatchString(str string) bool {
+ return string(m) == str
+}
+func (m ExactStringMatcher) String() string {
+ return string(m)
+}
+
+func assertRegexp(t *testing.T, input string, outputRE string) {
+ assertPlaintext(t, input, RegexpStringMatcher(outputRE))
+}
+
+func assertString(t *testing.T, input string, output string) {
+ assertPlaintext(t, input, ExactStringMatcher(output))
+}
+
+func assertPlaintext(t *testing.T, input string, matcher StringMatcher) {
+ text, err := FromString(input)
+ if err != nil {
+ t.Error(err)
+ }
+ if !matcher.MatchString(text) {
+ t.Errorf("Input did not match expression\n"+
+ "Input:\n>>>>\n%s\n<<<<\n\n"+
+ "Output:\n>>>>\n%s\n<<<<\n\n"+
+ "Expected output:\n>>>>\n%s\n<<<<\n\n",
+ input, text, matcher.String())
+ } else {
+ t.Logf("input:\n\n%s\n\n\n\noutput:\n\n%s\n", input, text)
+ }
+}
+
+func Example() {
+ inputHtml := `
+
+
+ My Mega Service
+
+
+
+
+
+
+
+
+
+ Welcome to your new account on my service!
+
+
+ Here is some more information:
+
+
+
+
+
+ `
+
+ text, err := FromString(inputHtml)
+ if err != nil {
+ panic(err)
+ }
+ fmt.Println(text)
+
+ // Output:
+ // Mega Service ( http://mymegaservice.com/ )
+ //
+ // ******************************************
+ // Welcome to your new account on my service!
+ // ******************************************
+ //
+ // Here is some more information:
+ //
+ // * Link 1: Example.com ( https://example.com )
+ // * Link 2: Example2.com ( https://example2.com )
+ // * Something else
+}
diff --git a/vendor/github.com/jaytaylor/html2text/testdata/utf8.html b/vendor/github.com/jaytaylor/html2text/testdata/utf8.html
new file mode 100755
index 0000000000..53d401ce91
--- /dev/null
+++ b/vendor/github.com/jaytaylor/html2text/testdata/utf8.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ 学习之道:美国公认学习第一书title
+
+
+
+
+
+ 写在前面的话
+
+ 在台湾的那次世界冠军赛上,我几近疯狂,直至两年后的今天,我仍沉浸在这次的经历中。这是我生平第一次如此深入地审视我自己,甚至是第一次尝试审视自己。这个过程令人很是兴奋,同时也有点感觉怪异。我重新认识了自我,看到了自己的另外一面,自己从未发觉的另外一面。为了生存,为了取胜,我成了一名角斗士,彻头彻尾,简单纯粹。我并没有意识到这一角色早已在我的心中生根发芽,呼之欲出。也许,他的出现已是不可避免。
+ 而我这全新的一面,与我一直熟识的那个乔希,那个曾经害怕黑暗的孩子,那个象棋手,那个狂热于雨水、反复诵读杰克·克鲁亚克作品的年轻人之间,又有什么样的联系呢?这些都是我正在努力弄清楚的问题。
+ 自台湾赛事之后,我急切非常,一心想要回到训练中去,摆脱自己已经达到巅峰的想法。在过去的两年中,我已经重新开始。这是一个新的起点。前方的路还很长,有待进一步的探索。
+ 这本书的创作耗费了相当多的时间和精力。在成长的过程中,我在我的小房间里从未想过等待我的会是这样的战斗。在创作中,我的思想逐渐成熟;爱恋从分崩离析,到失而复得,世界冠军头衔从失之交臂,到囊中取物。如果说在我人生的第一个二十九年中,我学到了什么,那就是,我们永远无法预测结局,无论是重要的比赛、冒险,还是轰轰烈烈的爱情。我们唯一可以肯定的只有,出乎意料。不管我们做了多么万全的准备,在生活的真实场景中,我们总是会处于陌生的境地。我们也许会无法冷静,失去理智,感觉似乎整个世界都在针对我们。在这个时候,我们所要做的是要付出加倍的努力,要表现得比预想得更好。我认为,关键在于准备好随机应变,准备好在所能想象的高压下发挥出创造力。
+ 读者朋友们,我非常希望你们在读过这本书后,可以得到启发,甚至会得到触动,从而能够根据各自的天赋与特长,去实现自己的梦想。这就是我写作此书的目的。我在字里行间所传达的理念曾经使我受益匪浅,我很希望它们可以为大家提供一个基本的框架和方向。如果我的方法言之有理,那么就请接受它,琢磨它,并加之自己的见解。忘记我的那些数字。真正的掌握需要通过自己发现一些最能够引起共鸣的信息,并将其彻底地融合进来,直至成为一体,这样我们才能随心所欲地驾驭它。
+
+
+
+
\ No newline at end of file
diff --git a/vendor/github.com/jaytaylor/html2text/testdata/utf8_with_bom.xhtml b/vendor/github.com/jaytaylor/html2text/testdata/utf8_with_bom.xhtml
new file mode 100755
index 0000000000..68f0ee707e
--- /dev/null
+++ b/vendor/github.com/jaytaylor/html2text/testdata/utf8_with_bom.xhtml
@@ -0,0 +1,24 @@
+
+
+
+
+
+ 1892年波兰文版序言title
+
+
+
+
+
+ 1892年波兰文版序言[18]
+ 出版共产主义宣言的一种新的波兰文本已成为必要,这一事实,引起了许多感想。
+ 首先值得注意的是,近来宣言在一定程度上已成为欧洲大陆大工业发展的一种尺度。一个国家的大工业越发展,该国工人中想认清自己作为工人阶级在有产阶级面前所处地位的要求就越增加,他们中间的社会主义运动也越扩大,因而对宣言的需求也越增长。这样,根据宣言用某国文字销行的份数,不仅能够相当确切地断定该国工人运动的状况,而且还能够相当确切地断定该国大工业发展的程度。
+ 因此,波兰文的新版本标志着波兰工业的决定性进步。从十年前发表的上一个版本以来确实有了这种进步,对此丝毫不容置疑。俄国的波兰,会议的波兰[19] ,成了俄罗斯帝国巨大的工业区。俄国大工业是零星分散的,一部分在芬兰湾沿岸,一部分在中央区(莫斯科和弗拉基米尔),第三部分在黑海和亚速海沿岸,还有另一些散布在别处;而波兰工业则紧缩于相对狭小的地区,享受到由这种积聚引起的长处与短处。这种长处是竞争着的俄罗斯工厂主所承认的,他们要求实行保护关税以对付波兰,尽管他们渴望使波兰人俄罗斯化。这种短处,对波兰工厂主与俄罗斯政府来说,表现在社会主义思想在波兰工人中间的迅速传播和对宣言需求的增长。
+ 但是,波兰工业的迅速发展——它超过了俄国工业——本身 是波兰人民的坚强生命力的一个新证明,是波兰人民临近的民族复兴的一个新保证。而一个独立强盛的波兰的复兴,不只是一件同波兰人有关、而且是同我们大家有关的事情。只有当每个民族在自己内部完全自主时,欧洲各民族间真诚的国际合作才是可能的。1848年革命在无产阶级旗帜下,使无产阶级的战士最终只作了资产阶级的工作,这次革命通过自己遗嘱的执行者路易·波拿巴和俾斯麦也实现了意大利、德国和匈牙利的独立。然而波兰,它从1792年以来为革命做的比所有这三个国家总共做的还要多,而当它1863年失败于强大十倍的俄军的时候,人们却把它抛弃不顾了。贵族既未能保持住、也未能重新争得波兰的独立;今天波兰的独立对资产阶级至少是无所谓的。然而波兰的独立对于欧洲各民族和谐的合作是必需的。这种独立只有年轻的波兰无产阶级才能争得,而且在它的手中会很好地保持住。因为欧洲所有其余的工人都象波兰工人自己一样也需要波兰的独立。
+ 弗·恩格斯
+ 1892年2月10日于伦敦
+
+ [18] 恩格斯用德文为《宣言》新的波兰文本写了这篇序言。1892年由波兰社会主义者在伦敦办的《黎明》杂志社出版。序言寄出后,恩格斯写信给门德尔森(1892年2月11日),信中说,他很愿意学会波兰文,并且深入研究波兰工人运动的发展,以便能够为《宣言》的下一版写一篇更详细的序言。——第20页
+ [19] 指维也纳会议的波兰,即根据1814—1815年维也纳会议的决定,以波兰王国的正式名义割给俄国的那部分波兰土地。——第20页
+
+
+
\ No newline at end of file
diff --git a/vendor/github.com/lib/pq/README.md b/vendor/github.com/lib/pq/README.md
index 5eb9e14450..7670fc87a5 100644
--- a/vendor/github.com/lib/pq/README.md
+++ b/vendor/github.com/lib/pq/README.md
@@ -1,6 +1,6 @@
# pq - A pure Go postgres driver for Go's database/sql package
-[](https://travis-ci.org/lib/pq)
+[](https://travis-ci.org/lib/pq)
## Install
diff --git a/vendor/github.com/lib/pq/conn.go b/vendor/github.com/lib/pq/conn.go
index 3c8f77cb6a..4b2fb4462c 100644
--- a/vendor/github.com/lib/pq/conn.go
+++ b/vendor/github.com/lib/pq/conn.go
@@ -133,7 +133,7 @@ type conn struct {
// Handle driver-side settings in parsed connection string.
func (c *conn) handleDriverSettings(o values) (err error) {
boolSetting := func(key string, val *bool) error {
- if value := o.Get(key); value != "" {
+ if value, ok := o[key]; ok {
if value == "yes" {
*val = true
} else if value == "no" {
@@ -158,8 +158,7 @@ func (c *conn) handleDriverSettings(o values) (err error) {
func (c *conn) handlePgpass(o values) {
// if a password was supplied, do not process .pgpass
- _, ok := o["password"]
- if ok {
+ if _, ok := o["password"]; ok {
return
}
filename := os.Getenv("PGPASSFILE")
@@ -187,11 +186,11 @@ func (c *conn) handlePgpass(o values) {
}
defer file.Close()
scanner := bufio.NewScanner(io.Reader(file))
- hostname := o.Get("host")
+ hostname := o["host"]
ntw, _ := network(o)
- port := o.Get("port")
- db := o.Get("dbname")
- username := o.Get("user")
+ port := o["port"]
+ db := o["dbname"]
+ username := o["user"]
// From: https://github.com/tg/pgpass/blob/master/reader.go
getFields := func(s string) []string {
fs := make([]string, 0, 5)
@@ -256,13 +255,13 @@ func DialOpen(d Dialer, name string) (_ driver.Conn, err error) {
// * Very low precedence defaults applied in every situation
// * Environment variables
// * Explicitly passed connection information
- o.Set("host", "localhost")
- o.Set("port", "5432")
+ o["host"] = "localhost"
+ o["port"] = "5432"
// N.B.: Extra float digits should be set to 3, but that breaks
// Postgres 8.4 and older, where the max is 2.
- o.Set("extra_float_digits", "2")
+ o["extra_float_digits"] = "2"
for k, v := range parseEnviron(os.Environ()) {
- o.Set(k, v)
+ o[k] = v
}
if strings.HasPrefix(name, "postgres://") || strings.HasPrefix(name, "postgresql://") {
@@ -277,9 +276,9 @@ func DialOpen(d Dialer, name string) (_ driver.Conn, err error) {
}
// Use the "fallback" application name if necessary
- if fallback := o.Get("fallback_application_name"); fallback != "" {
- if !o.Isset("application_name") {
- o.Set("application_name", fallback)
+ if fallback, ok := o["fallback_application_name"]; ok {
+ if _, ok := o["application_name"]; !ok {
+ o["application_name"] = fallback
}
}
@@ -290,29 +289,29 @@ func DialOpen(d Dialer, name string) (_ driver.Conn, err error) {
// parsing its value is not worth it. Instead, we always explicitly send
// client_encoding as a separate run-time parameter, which should override
// anything set in options.
- if enc := o.Get("client_encoding"); enc != "" && !isUTF8(enc) {
+ if enc, ok := o["client_encoding"]; ok && !isUTF8(enc) {
return nil, errors.New("client_encoding must be absent or 'UTF8'")
}
- o.Set("client_encoding", "UTF8")
+ o["client_encoding"] = "UTF8"
// DateStyle needs a similar treatment.
- if datestyle := o.Get("datestyle"); datestyle != "" {
+ if datestyle, ok := o["datestyle"]; ok {
if datestyle != "ISO, MDY" {
panic(fmt.Sprintf("setting datestyle must be absent or %v; got %v",
"ISO, MDY", datestyle))
}
} else {
- o.Set("datestyle", "ISO, MDY")
+ o["datestyle"] = "ISO, MDY"
}
// If a user is not provided by any other means, the last
// resort is to use the current operating system provided user
// name.
- if o.Get("user") == "" {
+ if _, ok := o["user"]; !ok {
u, err := userCurrent()
if err != nil {
return nil, err
} else {
- o.Set("user", u)
+ o["user"] = u
}
}
@@ -335,7 +334,7 @@ func DialOpen(d Dialer, name string) (_ driver.Conn, err error) {
cn.startup(o)
// reset the deadline, in case one was set (see dial)
- if timeout := o.Get("connect_timeout"); timeout != "" && timeout != "0" {
+ if timeout, ok := o["connect_timeout"]; ok && timeout != "0" {
err = cn.c.SetDeadline(time.Time{})
}
return cn, err
@@ -349,7 +348,7 @@ func dial(d Dialer, o values) (net.Conn, error) {
}
// Zero or not specified means wait indefinitely.
- if timeout := o.Get("connect_timeout"); timeout != "" && timeout != "0" {
+ if timeout, ok := o["connect_timeout"]; ok && timeout != "0" {
seconds, err := strconv.ParseInt(timeout, 10, 0)
if err != nil {
return nil, fmt.Errorf("invalid value for parameter connect_timeout: %s", err)
@@ -371,31 +370,18 @@ func dial(d Dialer, o values) (net.Conn, error) {
}
func network(o values) (string, string) {
- host := o.Get("host")
+ host := o["host"]
if strings.HasPrefix(host, "/") {
- sockPath := path.Join(host, ".s.PGSQL."+o.Get("port"))
+ sockPath := path.Join(host, ".s.PGSQL."+o["port"])
return "unix", sockPath
}
- return "tcp", net.JoinHostPort(host, o.Get("port"))
+ return "tcp", net.JoinHostPort(host, o["port"])
}
type values map[string]string
-func (vs values) Set(k, v string) {
- vs[k] = v
-}
-
-func (vs values) Get(k string) (v string) {
- return vs[k]
-}
-
-func (vs values) Isset(k string) bool {
- _, ok := vs[k]
- return ok
-}
-
// scanner implements a tokenizer for libpq-style option strings.
type scanner struct {
s []rune
@@ -466,7 +452,7 @@ func parseOpts(name string, o values) error {
// Skip any whitespace after the =
if r, ok = s.SkipSpaces(); !ok {
// If we reach the end here, the last value is just an empty string as per libpq.
- o.Set(string(keyRunes), "")
+ o[string(keyRunes)] = ""
break
}
@@ -501,7 +487,7 @@ func parseOpts(name string, o values) error {
}
}
- o.Set(string(keyRunes), string(valRunes))
+ o[string(keyRunes)] = string(valRunes)
}
return nil
@@ -665,6 +651,12 @@ func (cn *conn) simpleQuery(q string) (res *rows, err error) {
cn: cn,
}
}
+ // Set the result and tag to the last command complete if there wasn't a
+ // query already run. Although queries usually return from here and cede
+ // control to Next, a query with zero results does not.
+ if t == 'C' && res.colNames == nil {
+ res.result, res.tag = cn.parseComplete(r.string())
+ }
res.done = true
case 'Z':
cn.processReadyForQuery(r)
@@ -1119,7 +1111,7 @@ func (cn *conn) auth(r *readBuf, o values) {
// OK
case 3:
w := cn.writeBuf('p')
- w.string(o.Get("password"))
+ w.string(o["password"])
cn.send(w)
t, r := cn.recv()
@@ -1133,7 +1125,7 @@ func (cn *conn) auth(r *readBuf, o values) {
case 5:
s := string(r.next(4))
w := cn.writeBuf('p')
- w.string("md5" + md5s(md5s(o.Get("password")+o.Get("user"))+s))
+ w.string("md5" + md5s(md5s(o["password"]+o["user"])+s))
cn.send(w)
t, r := cn.recv()
@@ -1333,6 +1325,8 @@ type rows struct {
colFmts []format
done bool
rb readBuf
+ result driver.Result
+ tag string
}
func (rs *rows) Close() error {
@@ -1356,6 +1350,17 @@ func (rs *rows) Columns() []string {
return rs.colNames
}
+func (rs *rows) Result() driver.Result {
+ if rs.result == nil {
+ return emptyRows
+ }
+ return rs.result
+}
+
+func (rs *rows) Tag() string {
+ return rs.tag
+}
+
func (rs *rows) Next(dest []driver.Value) (err error) {
if rs.done {
return io.EOF
@@ -1373,6 +1378,9 @@ func (rs *rows) Next(dest []driver.Value) (err error) {
case 'E':
err = parseError(&rs.rb)
case 'C', 'I':
+ if t == 'C' {
+ rs.result, rs.tag = conn.parseComplete(rs.rb.string())
+ }
continue
case 'Z':
conn.processReadyForQuery(&rs.rb)
diff --git a/vendor/github.com/lib/pq/conn_go18.go b/vendor/github.com/lib/pq/conn_go18.go
index 0aca1d0027..43cc35f7b4 100644
--- a/vendor/github.com/lib/pq/conn_go18.go
+++ b/vendor/github.com/lib/pq/conn_go18.go
@@ -14,10 +14,7 @@ func (cn *conn) QueryContext(ctx context.Context, query string, args []driver.Na
for i, nv := range args {
list[i] = nv.Value
}
- var closed chan<- struct{}
- if ctx.Done() != nil {
- closed = watchCancel(ctx, cn.cancel)
- }
+ closed := cn.watchCancel(ctx)
r, err := cn.query(query, list)
if err != nil {
return nil, err
@@ -33,8 +30,7 @@ func (cn *conn) ExecContext(ctx context.Context, query string, args []driver.Nam
list[i] = nv.Value
}
- if ctx.Done() != nil {
- closed := watchCancel(ctx, cn.cancel)
+ if closed := cn.watchCancel(ctx); closed != nil {
defer close(closed)
}
@@ -53,22 +49,23 @@ func (cn *conn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx,
if err != nil {
return nil, err
}
- if ctx.Done() != nil {
- cn.txnClosed = watchCancel(ctx, cn.cancel)
- }
+ cn.txnClosed = cn.watchCancel(ctx)
return tx, nil
}
-func watchCancel(ctx context.Context, cancel func()) chan<- struct{} {
- closed := make(chan struct{})
- go func() {
- select {
- case <-ctx.Done():
- cancel()
- case <-closed:
- }
- }()
- return closed
+func (cn *conn) watchCancel(ctx context.Context) chan<- struct{} {
+ if done := ctx.Done(); done != nil {
+ closed := make(chan struct{})
+ go func() {
+ select {
+ case <-done:
+ cn.cancel()
+ case <-closed:
+ }
+ }()
+ return closed
+ }
+ return nil
}
func (cn *conn) cancel() {
diff --git a/vendor/github.com/lib/pq/conn_test.go b/vendor/github.com/lib/pq/conn_test.go
index 183e6dcd62..c9135b7274 100644
--- a/vendor/github.com/lib/pq/conn_test.go
+++ b/vendor/github.com/lib/pq/conn_test.go
@@ -191,7 +191,7 @@ localhost:*:*:*:pass_C
pgpass.Close()
assertPassword := func(extra values, expected string) {
- o := &values{
+ o := values{
"host": "localhost",
"sslmode": "disable",
"connect_timeout": "20",
@@ -203,11 +203,11 @@ localhost:*:*:*:pass_C
"datestyle": "ISO, MDY",
}
for k, v := range extra {
- (*o)[k] = v
+ o[k] = v
}
- (&conn{}).handlePgpass(*o)
- if o.Get("password") != expected {
- t.Fatalf("For %v expected %s got %s", extra, expected, o.Get("password"))
+ (&conn{}).handlePgpass(o)
+ if pw := o["password"]; pw != expected {
+ t.Fatalf("For %v expected %s got %s", extra, expected, pw)
}
}
// wrong permissions for the pgpass file means it should be ignored
@@ -686,17 +686,28 @@ func TestCloseBadConn(t *testing.T) {
if err := cn.Close(); err != nil {
t.Fatal(err)
}
+
+ // During the Go 1.9 cycle, https://github.com/golang/go/commit/3792db5
+ // changed this error from
+ //
+ // net.errClosing = errors.New("use of closed network connection")
+ //
+ // to
+ //
+ // internal/poll.ErrClosing = errors.New("use of closed file or network connection")
+ const errClosing = "use of closed"
+
// Verify write after closing fails.
if _, err := nc.Write(nil); err == nil {
t.Fatal("expected error")
- } else if !strings.Contains(err.Error(), "use of closed network connection") {
- t.Fatalf("expected use of closed network connection error, got %s", err)
+ } else if !strings.Contains(err.Error(), errClosing) {
+ t.Fatalf("expected %s error, got %s", errClosing, err)
}
// Verify second close fails.
if err := cn.Close(); err == nil {
t.Fatal("expected error")
- } else if !strings.Contains(err.Error(), "use of closed network connection") {
- t.Fatalf("expected use of closed network connection error, got %s", err)
+ } else if !strings.Contains(err.Error(), errClosing) {
+ t.Fatalf("expected %s error, got %s", errClosing, err)
}
}
@@ -1493,3 +1504,82 @@ func TestQuoteIdentifier(t *testing.T) {
}
}
}
+
+func TestRowsResultTag(t *testing.T) {
+ type ResultTag interface {
+ Result() driver.Result
+ Tag() string
+ }
+
+ tests := []struct {
+ query string
+ tag string
+ ra int64
+ }{
+ {
+ query: "CREATE TEMP TABLE temp (a int)",
+ tag: "CREATE TABLE",
+ },
+ {
+ query: "INSERT INTO temp VALUES (1), (2)",
+ tag: "INSERT",
+ ra: 2,
+ },
+ {
+ query: "SELECT 1",
+ },
+ // A SELECT anywhere should take precedent.
+ {
+ query: "SELECT 1; INSERT INTO temp VALUES (1), (2)",
+ },
+ {
+ query: "INSERT INTO temp VALUES (1), (2); SELECT 1",
+ },
+ // Multiple statements that don't return rows should return the last tag.
+ {
+ query: "CREATE TEMP TABLE t (a int); DROP TABLE t",
+ tag: "DROP TABLE",
+ },
+ // Ensure a rows-returning query in any position among various tags-returing
+ // statements will prefer the rows.
+ {
+ query: "SELECT 1; CREATE TEMP TABLE t (a int); DROP TABLE t",
+ },
+ {
+ query: "CREATE TEMP TABLE t (a int); SELECT 1; DROP TABLE t",
+ },
+ {
+ query: "CREATE TEMP TABLE t (a int); DROP TABLE t; SELECT 1",
+ },
+ // Verify that an no-results query doesn't set the tag.
+ {
+ query: "CREATE TEMP TABLE t (a int); SELECT 1 WHERE FALSE; DROP TABLE t;",
+ },
+ }
+
+ // If this is the only test run, this will correct the connection string.
+ openTestConn(t).Close()
+
+ conn, err := Open("")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer conn.Close()
+ q := conn.(driver.Queryer)
+
+ for _, test := range tests {
+ if rows, err := q.Query(test.query, nil); err != nil {
+ t.Fatalf("%s: %s", test.query, err)
+ } else {
+ r := rows.(ResultTag)
+ if tag := r.Tag(); tag != test.tag {
+ t.Fatalf("%s: unexpected tag %q", test.query, tag)
+ }
+ res := r.Result()
+ if ra, _ := res.RowsAffected(); ra != test.ra {
+ t.Fatalf("%s: unexpected rows affected: %d", test.query, ra)
+ }
+ rows.Close()
+ }
+ }
+}
diff --git a/vendor/github.com/lib/pq/go18_test.go b/vendor/github.com/lib/pq/go18_test.go
index 15546d865b..5d17e4d92c 100644
--- a/vendor/github.com/lib/pq/go18_test.go
+++ b/vendor/github.com/lib/pq/go18_test.go
@@ -79,10 +79,7 @@ func TestContextCancelExec(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
// Delay execution for just a bit until db.ExecContext has begun.
- go func() {
- time.Sleep(time.Millisecond * 10)
- cancel()
- }()
+ defer time.AfterFunc(time.Millisecond*10, cancel).Stop()
// Not canceled until after the exec has started.
if _, err := db.ExecContext(ctx, "select pg_sleep(1)"); err == nil {
@@ -106,10 +103,7 @@ func TestContextCancelQuery(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
// Delay execution for just a bit until db.QueryContext has begun.
- go func() {
- time.Sleep(time.Millisecond * 10)
- cancel()
- }()
+ defer time.AfterFunc(time.Millisecond*10, cancel).Stop()
// Not canceled until after the exec has started.
if _, err := db.QueryContext(ctx, "select pg_sleep(1)"); err == nil {
@@ -137,10 +131,7 @@ func TestContextCancelBegin(t *testing.T) {
}
// Delay execution for just a bit until tx.Exec has begun.
- go func() {
- time.Sleep(time.Millisecond * 10)
- cancel()
- }()
+ defer time.AfterFunc(time.Millisecond*10, cancel).Stop()
// Not canceled until after the exec has started.
if _, err := tx.Exec("select pg_sleep(1)"); err == nil {
diff --git a/vendor/github.com/lib/pq/listen_example/doc.go b/vendor/github.com/lib/pq/listen_example/doc.go
index 5bc99f5c19..80f0a9b970 100644
--- a/vendor/github.com/lib/pq/listen_example/doc.go
+++ b/vendor/github.com/lib/pq/listen_example/doc.go
@@ -51,21 +51,15 @@ mechanism to avoid polling the database while waiting for more work to arrive.
}
func waitForNotification(l *pq.Listener) {
- for {
- select {
- case <-l.Notify:
- fmt.Println("received notification, new work available")
- return
- case <-time.After(90 * time.Second):
- go func() {
- l.Ping()
- }()
- // Check if there's more work available, just in case it takes
- // a while for the Listener to notice connection loss and
- // reconnect.
- fmt.Println("received no work for 90 seconds, checking for new work")
- return
- }
+ select {
+ case <-l.Notify:
+ fmt.Println("received notification, new work available")
+ case <-time.After(90 * time.Second):
+ go l.Ping()
+ // Check if there's more work available, just in case it takes
+ // a while for the Listener to notice connection loss and
+ // reconnect.
+ fmt.Println("received no work for 90 seconds, checking for new work")
}
}
diff --git a/vendor/github.com/lib/pq/notify_test.go b/vendor/github.com/lib/pq/notify_test.go
index fe8941a4e0..82a77e1ebc 100644
--- a/vendor/github.com/lib/pq/notify_test.go
+++ b/vendor/github.com/lib/pq/notify_test.go
@@ -7,7 +7,6 @@ import (
"os"
"runtime"
"sync"
- "sync/atomic"
"testing"
"time"
)
@@ -235,15 +234,10 @@ func TestConnExecDeadlock(t *testing.T) {
// calls Close on the net.Conn; equivalent to a network failure
l.Close()
- var done int32 = 0
- go func() {
- time.Sleep(10 * time.Second)
- if atomic.LoadInt32(&done) != 1 {
- panic("timed out")
- }
- }()
+ defer time.AfterFunc(10*time.Second, func() {
+ panic("timed out")
+ }).Stop()
wg.Wait()
- atomic.StoreInt32(&done, 1)
}
// Test for ListenerConn being closed while a slow query is executing
@@ -271,15 +265,11 @@ func TestListenerConnCloseWhileQueryIsExecuting(t *testing.T) {
if err != nil {
t.Fatal(err)
}
- var done int32 = 0
- go func() {
- time.Sleep(10 * time.Second)
- if atomic.LoadInt32(&done) != 1 {
- panic("timed out")
- }
- }()
+
+ defer time.AfterFunc(10*time.Second, func() {
+ panic("timed out")
+ }).Stop()
wg.Wait()
- atomic.StoreInt32(&done, 1)
}
func TestNotifyExtra(t *testing.T) {
diff --git a/vendor/github.com/lib/pq/oid/types.go b/vendor/github.com/lib/pq/oid/types.go
index 03df05a617..a3390c23a8 100644
--- a/vendor/github.com/lib/pq/oid/types.go
+++ b/vendor/github.com/lib/pq/oid/types.go
@@ -18,6 +18,7 @@ const (
T_xid Oid = 28
T_cid Oid = 29
T_oidvector Oid = 30
+ T_pg_ddl_command Oid = 32
T_pg_type Oid = 71
T_pg_attribute Oid = 75
T_pg_proc Oid = 81
@@ -28,6 +29,7 @@ const (
T_pg_node_tree Oid = 194
T__json Oid = 199
T_smgr Oid = 210
+ T_index_am_handler Oid = 325
T_point Oid = 600
T_lseg Oid = 601
T_path Oid = 602
@@ -133,6 +135,9 @@ const (
T__uuid Oid = 2951
T_txid_snapshot Oid = 2970
T_fdw_handler Oid = 3115
+ T_pg_lsn Oid = 3220
+ T__pg_lsn Oid = 3221
+ T_tsm_handler Oid = 3310
T_anyenum Oid = 3500
T_tsvector Oid = 3614
T_tsquery Oid = 3615
@@ -144,6 +149,8 @@ const (
T__regconfig Oid = 3735
T_regdictionary Oid = 3769
T__regdictionary Oid = 3770
+ T_jsonb Oid = 3802
+ T__jsonb Oid = 3807
T_anyrange Oid = 3831
T_event_trigger Oid = 3838
T_int4range Oid = 3904
@@ -158,4 +165,9 @@ const (
T__daterange Oid = 3913
T_int8range Oid = 3926
T__int8range Oid = 3927
+ T_pg_shseclabel Oid = 4066
+ T_regnamespace Oid = 4089
+ T__regnamespace Oid = 4090
+ T_regrole Oid = 4096
+ T__regrole Oid = 4097
)
diff --git a/vendor/github.com/lib/pq/ssl.go b/vendor/github.com/lib/pq/ssl.go
index b282ebd926..7deb304366 100644
--- a/vendor/github.com/lib/pq/ssl.go
+++ b/vendor/github.com/lib/pq/ssl.go
@@ -15,7 +15,7 @@ import (
func ssl(o values) func(net.Conn) net.Conn {
verifyCaOnly := false
tlsConf := tls.Config{}
- switch mode := o.Get("sslmode"); mode {
+ switch mode := o["sslmode"]; mode {
// "require" is the default.
case "", "require":
// We must skip TLS's own verification since it requires full
@@ -23,15 +23,19 @@ func ssl(o values) func(net.Conn) net.Conn {
tlsConf.InsecureSkipVerify = true
// From http://www.postgresql.org/docs/current/static/libpq-ssl.html:
- // Note: For backwards compatibility with earlier versions of PostgreSQL, if a
- // root CA file exists, the behavior of sslmode=require will be the same as
- // that of verify-ca, meaning the server certificate is validated against the
- // CA. Relying on this behavior is discouraged, and applications that need
- // certificate validation should always use verify-ca or verify-full.
- if _, err := os.Stat(o.Get("sslrootcert")); err == nil {
- verifyCaOnly = true
- } else {
- o.Set("sslrootcert", "")
+ //
+ // Note: For backwards compatibility with earlier versions of
+ // PostgreSQL, if a root CA file exists, the behavior of
+ // sslmode=require will be the same as that of verify-ca, meaning the
+ // server certificate is validated against the CA. Relying on this
+ // behavior is discouraged, and applications that need certificate
+ // validation should always use verify-ca or verify-full.
+ if sslrootcert, ok := o["sslrootcert"]; ok {
+ if _, err := os.Stat(sslrootcert); err == nil {
+ verifyCaOnly = true
+ } else {
+ delete(o, "sslrootcert")
+ }
}
case "verify-ca":
// We must skip TLS's own verification since it requires full
@@ -39,7 +43,7 @@ func ssl(o values) func(net.Conn) net.Conn {
tlsConf.InsecureSkipVerify = true
verifyCaOnly = true
case "verify-full":
- tlsConf.ServerName = o.Get("host")
+ tlsConf.ServerName = o["host"]
case "disable":
return nil
default:
@@ -64,37 +68,42 @@ func ssl(o values) func(net.Conn) net.Conn {
// in the user's home directory. The configured files must exist and have
// the correct permissions.
func sslClientCertificates(tlsConf *tls.Config, o values) {
- sslkey := o.Get("sslkey")
- sslcert := o.Get("sslcert")
+ // user.Current() might fail when cross-compiling. We have to ignore the
+ // error and continue without home directory defaults, since we wouldn't
+ // know from where to load them.
+ user, _ := user.Current()
- var cinfo, kinfo os.FileInfo
- var err error
-
- if sslcert != "" && sslkey != "" {
- // Check that both files exist. Note that we don't do any more extensive
- // checks than this (such as checking that the paths aren't directories);
- // LoadX509KeyPair() will take care of the rest.
- cinfo, err = os.Stat(sslcert)
- if err != nil {
- panic(err)
- }
-
- kinfo, err = os.Stat(sslkey)
- if err != nil {
- panic(err)
- }
- } else {
- // Automatically find certificates from ~/.postgresql
- sslcert, sslkey, cinfo, kinfo = sslHomeCertificates()
-
- if cinfo == nil || kinfo == nil {
- // No certificates to load
- return
- }
+ // In libpq, the client certificate is only loaded if the setting is not blank.
+ //
+ // https://github.com/postgres/postgres/blob/REL9_6_2/src/interfaces/libpq/fe-secure-openssl.c#L1036-L1037
+ sslcert := o["sslcert"]
+ if len(sslcert) == 0 && user != nil {
+ sslcert = filepath.Join(user.HomeDir, ".postgresql", "postgresql.crt")
+ }
+ // https://github.com/postgres/postgres/blob/REL9_6_2/src/interfaces/libpq/fe-secure-openssl.c#L1045
+ if len(sslcert) == 0 {
+ return
+ }
+ // https://github.com/postgres/postgres/blob/REL9_6_2/src/interfaces/libpq/fe-secure-openssl.c#L1050:L1054
+ if _, err := os.Stat(sslcert); os.IsNotExist(err) {
+ return
+ } else if err != nil {
+ panic(err)
}
- // The files must also have the correct permissions
- sslCertificatePermissions(cinfo, kinfo)
+ // In libpq, the ssl key is only loaded if the setting is not blank.
+ //
+ // https://github.com/postgres/postgres/blob/REL9_6_2/src/interfaces/libpq/fe-secure-openssl.c#L1123-L1222
+ sslkey := o["sslkey"]
+ if len(sslkey) == 0 && user != nil {
+ sslkey = filepath.Join(user.HomeDir, ".postgresql", "postgresql.key")
+ }
+
+ if len(sslkey) > 0 {
+ if err := sslKeyPermissions(sslkey); err != nil {
+ panic(err)
+ }
+ }
cert, err := tls.LoadX509KeyPair(sslcert, sslkey)
if err != nil {
@@ -105,7 +114,10 @@ func sslClientCertificates(tlsConf *tls.Config, o values) {
// sslCertificateAuthority adds the RootCA specified in the "sslrootcert" setting.
func sslCertificateAuthority(tlsConf *tls.Config, o values) {
- if sslrootcert := o.Get("sslrootcert"); sslrootcert != "" {
+ // In libpq, the root certificate is only loaded if the setting is not blank.
+ //
+ // https://github.com/postgres/postgres/blob/REL9_6_2/src/interfaces/libpq/fe-secure-openssl.c#L950-L951
+ if sslrootcert := o["sslrootcert"]; len(sslrootcert) > 0 {
tlsConf.RootCAs = x509.NewCertPool()
cert, err := ioutil.ReadFile(sslrootcert)
@@ -113,41 +125,12 @@ func sslCertificateAuthority(tlsConf *tls.Config, o values) {
panic(err)
}
- ok := tlsConf.RootCAs.AppendCertsFromPEM(cert)
- if !ok {
+ if !tlsConf.RootCAs.AppendCertsFromPEM(cert) {
errorf("couldn't parse pem in sslrootcert")
}
}
}
-// sslHomeCertificates returns the path and stats of certificates in the current
-// user's home directory.
-func sslHomeCertificates() (cert, key string, cinfo, kinfo os.FileInfo) {
- user, err := user.Current()
-
- if err != nil {
- // user.Current() might fail when cross-compiling. We have to ignore the
- // error and continue without client certificates, since we wouldn't know
- // from where to load them.
- return
- }
-
- cert = filepath.Join(user.HomeDir, ".postgresql", "postgresql.crt")
- key = filepath.Join(user.HomeDir, ".postgresql", "postgresql.key")
-
- cinfo, err = os.Stat(cert)
- if err != nil {
- cinfo = nil
- }
-
- kinfo, err = os.Stat(key)
- if err != nil {
- kinfo = nil
- }
-
- return
-}
-
// sslVerifyCertificateAuthority carries out a TLS handshake to the server and
// verifies the presented certificate against the CA, i.e. the one specified in
// sslrootcert or the system CA if sslrootcert was not specified.
diff --git a/vendor/github.com/lib/pq/ssl_permissions.go b/vendor/github.com/lib/pq/ssl_permissions.go
index 33076a8daa..3b7c3a2a31 100644
--- a/vendor/github.com/lib/pq/ssl_permissions.go
+++ b/vendor/github.com/lib/pq/ssl_permissions.go
@@ -4,13 +4,17 @@ package pq
import "os"
-// sslCertificatePermissions checks the permissions on user-supplied certificate
-// files. The key file should have very little access.
+// sslKeyPermissions checks the permissions on user-supplied ssl key files.
+// The key file should have very little access.
//
// libpq does not check key file permissions on Windows.
-func sslCertificatePermissions(cert, key os.FileInfo) {
- kmode := key.Mode()
- if kmode != kmode&0600 {
- panic(ErrSSLKeyHasWorldPermissions)
+func sslKeyPermissions(sslkey string) error {
+ info, err := os.Stat(sslkey)
+ if err != nil {
+ return err
}
+ if info.Mode().Perm()&0077 != 0 {
+ return ErrSSLKeyHasWorldPermissions
+ }
+ return nil
}
diff --git a/vendor/github.com/lib/pq/ssl_test.go b/vendor/github.com/lib/pq/ssl_test.go
index f70a5fd578..3eafbfd20f 100644
--- a/vendor/github.com/lib/pq/ssl_test.go
+++ b/vendor/github.com/lib/pq/ssl_test.go
@@ -6,7 +6,6 @@ import (
_ "crypto/sha256"
"crypto/x509"
"database/sql"
- "fmt"
"os"
"path/filepath"
"testing"
@@ -42,10 +41,13 @@ func openSSLConn(t *testing.T, conninfo string) (*sql.DB, error) {
}
func checkSSLSetup(t *testing.T, conninfo string) {
- db, err := openSSLConn(t, conninfo)
- if err == nil {
- db.Close()
- t.Fatalf("expected error with conninfo=%q", conninfo)
+ _, err := openSSLConn(t, conninfo)
+ if pge, ok := err.(*Error); ok {
+ if pge.Code.Name() != "invalid_authorization_specification" {
+ t.Fatalf("unexpected error code '%s'", pge.Code.Name())
+ }
+ } else {
+ t.Fatalf("expected %T, got %v", (*Error)(nil), err)
}
}
@@ -150,120 +152,128 @@ func TestSSLVerifyCA(t *testing.T) {
checkSSLSetup(t, "sslmode=disable user=pqgossltest")
// Not OK according to the system CA
- _, err := openSSLConn(t, "host=postgres sslmode=verify-ca user=pqgossltest")
- if err == nil {
- t.Fatal("expected error")
+ {
+ _, err := openSSLConn(t, "host=postgres sslmode=verify-ca user=pqgossltest")
+ if _, ok := err.(x509.UnknownAuthorityError); !ok {
+ t.Fatalf("expected %T, got %#+v", x509.UnknownAuthorityError{}, err)
+ }
}
- _, ok := err.(x509.UnknownAuthorityError)
- if !ok {
- t.Fatalf("expected x509.UnknownAuthorityError, got %#+v", err)
+
+ // Still not OK according to the system CA; empty sslrootcert is treated as unspecified.
+ {
+ _, err := openSSLConn(t, "host=postgres sslmode=verify-ca user=pqgossltest sslrootcert=''")
+ if _, ok := err.(x509.UnknownAuthorityError); !ok {
+ t.Fatalf("expected %T, got %#+v", x509.UnknownAuthorityError{}, err)
+ }
}
rootCertPath := filepath.Join(os.Getenv("PQSSLCERTTEST_PATH"), "root.crt")
rootCert := "sslrootcert=" + rootCertPath + " "
// No match on Common Name, but that's OK
- _, err = openSSLConn(t, rootCert+"host=127.0.0.1 sslmode=verify-ca user=pqgossltest")
- if err != nil {
+ if _, err := openSSLConn(t, rootCert+"host=127.0.0.1 sslmode=verify-ca user=pqgossltest"); err != nil {
t.Fatal(err)
}
// Everything OK
- _, err = openSSLConn(t, rootCert+"host=postgres sslmode=verify-ca user=pqgossltest")
- if err != nil {
+ if _, err := openSSLConn(t, rootCert+"host=postgres sslmode=verify-ca user=pqgossltest"); err != nil {
t.Fatal(err)
}
}
-func getCertConninfo(t *testing.T, source string) string {
- var sslkey string
- var sslcert string
-
- certpath := os.Getenv("PQSSLCERTTEST_PATH")
-
- switch source {
- case "missingkey":
- sslkey = "/tmp/filedoesnotexist"
- sslcert = filepath.Join(certpath, "postgresql.crt")
- case "missingcert":
- sslkey = filepath.Join(certpath, "postgresql.key")
- sslcert = "/tmp/filedoesnotexist"
- case "certtwice":
- sslkey = filepath.Join(certpath, "postgresql.crt")
- sslcert = filepath.Join(certpath, "postgresql.crt")
- case "valid":
- sslkey = filepath.Join(certpath, "postgresql.key")
- sslcert = filepath.Join(certpath, "postgresql.crt")
- default:
- t.Fatalf("invalid source %q", source)
- }
- return fmt.Sprintf("sslmode=require user=pqgosslcert sslkey=%s sslcert=%s", sslkey, sslcert)
-}
-
// Authenticate over SSL using client certificates
func TestSSLClientCertificates(t *testing.T) {
maybeSkipSSLTests(t)
// Environment sanity check: should fail without SSL
checkSSLSetup(t, "sslmode=disable user=pqgossltest")
- // Should also fail without a valid certificate
- db, err := openSSLConn(t, "sslmode=require user=pqgosslcert")
- if err == nil {
- db.Close()
- t.Fatal("expected error")
+ const baseinfo = "sslmode=require user=pqgosslcert"
+
+ // Certificate not specified, should fail
+ {
+ _, err := openSSLConn(t, baseinfo)
+ if pge, ok := err.(*Error); ok {
+ if pge.Code.Name() != "invalid_authorization_specification" {
+ t.Fatalf("unexpected error code '%s'", pge.Code.Name())
+ }
+ } else {
+ t.Fatalf("expected %T, got %v", (*Error)(nil), err)
+ }
}
- pge, ok := err.(*Error)
+
+ // Empty certificate specified, should fail
+ {
+ _, err := openSSLConn(t, baseinfo+" sslcert=''")
+ if pge, ok := err.(*Error); ok {
+ if pge.Code.Name() != "invalid_authorization_specification" {
+ t.Fatalf("unexpected error code '%s'", pge.Code.Name())
+ }
+ } else {
+ t.Fatalf("expected %T, got %v", (*Error)(nil), err)
+ }
+ }
+
+ // Non-existent certificate specified, should fail
+ {
+ _, err := openSSLConn(t, baseinfo+" sslcert=/tmp/filedoesnotexist")
+ if pge, ok := err.(*Error); ok {
+ if pge.Code.Name() != "invalid_authorization_specification" {
+ t.Fatalf("unexpected error code '%s'", pge.Code.Name())
+ }
+ } else {
+ t.Fatalf("expected %T, got %v", (*Error)(nil), err)
+ }
+ }
+
+ certpath, ok := os.LookupEnv("PQSSLCERTTEST_PATH")
if !ok {
- t.Fatal("expected pq.Error")
+ t.Fatalf("PQSSLCERTTEST_PATH not present in environment")
}
- if pge.Code.Name() != "invalid_authorization_specification" {
- t.Fatalf("unexpected error code %q", pge.Code.Name())
+
+ sslcert := filepath.Join(certpath, "postgresql.crt")
+
+ // Cert present, key not specified, should fail
+ {
+ _, err := openSSLConn(t, baseinfo+" sslcert="+sslcert)
+ if _, ok := err.(*os.PathError); !ok {
+ t.Fatalf("expected %T, got %#+v", (*os.PathError)(nil), err)
+ }
}
+ // Cert present, empty key specified, should fail
+ {
+ _, err := openSSLConn(t, baseinfo+" sslcert="+sslcert+" sslkey=''")
+ if _, ok := err.(*os.PathError); !ok {
+ t.Fatalf("expected %T, got %#+v", (*os.PathError)(nil), err)
+ }
+ }
+
+ // Cert present, non-existent key, should fail
+ {
+ _, err := openSSLConn(t, baseinfo+" sslcert="+sslcert+" sslkey=/tmp/filedoesnotexist")
+ if _, ok := err.(*os.PathError); !ok {
+ t.Fatalf("expected %T, got %#+v", (*os.PathError)(nil), err)
+ }
+ }
+
+ // Key has wrong permissions (passing the cert as the key), should fail
+ if _, err := openSSLConn(t, baseinfo+" sslcert="+sslcert+" sslkey="+sslcert); err != ErrSSLKeyHasWorldPermissions {
+ t.Fatalf("expected %s, got %#+v", ErrSSLKeyHasWorldPermissions, err)
+ }
+
+ sslkey := filepath.Join(certpath, "postgresql.key")
+
// Should work
- db, err = openSSLConn(t, getCertConninfo(t, "valid"))
- if err != nil {
+ if db, err := openSSLConn(t, baseinfo+" sslcert="+sslcert+" sslkey="+sslkey); err != nil {
t.Fatal(err)
- }
- rows, err := db.Query("SELECT 1")
- if err != nil {
- t.Fatal(err)
- }
- rows.Close()
-}
-
-// Test errors with ssl certificates
-func TestSSLClientCertificatesMissingFiles(t *testing.T) {
- maybeSkipSSLTests(t)
- // Environment sanity check: should fail without SSL
- checkSSLSetup(t, "sslmode=disable user=pqgossltest")
-
- // Key missing, should fail
- _, err := openSSLConn(t, getCertConninfo(t, "missingkey"))
- if err == nil {
- t.Fatal("expected error")
- }
- // should be a PathError
- _, ok := err.(*os.PathError)
- if !ok {
- t.Fatalf("expected PathError, got %#+v", err)
- }
-
- // Cert missing, should fail
- _, err = openSSLConn(t, getCertConninfo(t, "missingcert"))
- if err == nil {
- t.Fatal("expected error")
- }
- // should be a PathError
- _, ok = err.(*os.PathError)
- if !ok {
- t.Fatalf("expected PathError, got %#+v", err)
- }
-
- // Key has wrong permissions, should fail
- _, err = openSSLConn(t, getCertConninfo(t, "certtwice"))
- if err == nil {
- t.Fatal("expected error")
- }
- if err != ErrSSLKeyHasWorldPermissions {
- t.Fatalf("expected ErrSSLKeyHasWorldPermissions, got %#+v", err)
+ } else {
+ rows, err := db.Query("SELECT 1")
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := rows.Close(); err != nil {
+ t.Fatal(err)
+ }
+ if err := db.Close(); err != nil {
+ t.Fatal(err)
+ }
}
}
diff --git a/vendor/github.com/lib/pq/ssl_windows.go b/vendor/github.com/lib/pq/ssl_windows.go
index 529daed225..5d2c763ceb 100644
--- a/vendor/github.com/lib/pq/ssl_windows.go
+++ b/vendor/github.com/lib/pq/ssl_windows.go
@@ -2,8 +2,8 @@
package pq
-import "os"
-
-// sslCertificatePermissions checks the permissions on user-supplied certificate
-// files. In libpq, this is a no-op on Windows.
-func sslCertificatePermissions(cert, key os.FileInfo) {}
+// sslKeyPermissions checks the permissions on user-supplied ssl key files.
+// The key file should have very little access.
+//
+// libpq does not check key file permissions on Windows.
+func sslKeyPermissions(string) error { return nil }
diff --git a/vendor/github.com/miekg/dns/README.md b/vendor/github.com/miekg/dns/README.md
index 0c1f1b6a9c..2acc7f1ff9 100644
--- a/vendor/github.com/miekg/dns/README.md
+++ b/vendor/github.com/miekg/dns/README.md
@@ -25,6 +25,7 @@ two versions of Go, currently: 1.6 and 1.7.
A not-so-up-to-date-list-that-may-be-actually-current:
+* https://github.com/coredns/coredns
* https://cloudflare.com
* https://github.com/abh/geodns
* http://www.statdns.com/
@@ -54,6 +55,8 @@ A not-so-up-to-date-list-that-may-be-actually-current:
* https://github.com/mehrdadrad/mylg
* https://github.com/bamarni/dockness
* https://github.com/fffaraz/microdns
+* http://quilt.io
+* https://github.com/ipdcode/hades (JD.COM)
Send pull request if you want to be listed here.
@@ -142,6 +145,7 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
* 6975 - Algorithm Understanding in DNSSEC
* 7043 - EUI48/EUI64 records
* 7314 - DNS (EDNS) EXPIRE Option
+* 7828 - edns-tcp-keepalive EDNS0 Option
* 7553 - URI record
* 7858 - DNS over TLS: Initiation and Performance Considerations (draft)
* 7873 - Domain Name System (DNS) Cookies (draft-ietf-dnsop-cookies)
diff --git a/vendor/github.com/miekg/dns/client.go b/vendor/github.com/miekg/dns/client.go
index 0db7f7bf68..d54d6422e1 100644
--- a/vendor/github.com/miekg/dns/client.go
+++ b/vendor/github.com/miekg/dns/client.go
@@ -121,12 +121,12 @@ func (c *Client) Exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err erro
r, rtt, err, shared := c.group.Do(m.Question[0].Name+t+cl, func() (*Msg, time.Duration, error) {
return c.exchange(m, a)
})
+ if r != nil && shared {
+ r = r.Copy()
+ }
if err != nil {
return r, rtt, err
}
- if shared {
- return r.Copy(), rtt, nil
- }
return r, rtt, nil
}
@@ -300,6 +300,18 @@ func tcpMsgLen(t io.Reader) (int, error) {
if err != nil {
return 0, err
}
+
+ // As seen with my local router/switch, retursn 1 byte on the above read,
+ // resulting a a ShortRead. Just write it out (instead of loop) and read the
+ // other byte.
+ if n == 1 {
+ n1, err := t.Read(p[1:])
+ if err != nil {
+ return 0, err
+ }
+ n += n1
+ }
+
if n != 2 {
return 0, ErrShortRead
}
@@ -400,7 +412,7 @@ func (co *Conn) Write(p []byte) (n int, err error) {
n, err := io.Copy(w, bytes.NewReader(p))
return int(n), err
}
- n, err = co.Conn.(*net.UDPConn).Write(p)
+ n, err = co.Conn.Write(p)
return n, err
}
diff --git a/vendor/github.com/miekg/dns/client_test.go b/vendor/github.com/miekg/dns/client_test.go
index 850bcfcda6..dee585f367 100644
--- a/vendor/github.com/miekg/dns/client_test.go
+++ b/vendor/github.com/miekg/dns/client_test.go
@@ -5,6 +5,7 @@ import (
"fmt"
"net"
"strconv"
+ "sync"
"testing"
"time"
)
@@ -77,8 +78,8 @@ func TestClientTLSSync(t *testing.T) {
}
}
-func TestClientSyncBadId(t *testing.T) {
- HandleFunc("miek.nl.", HelloServerBadId)
+func TestClientSyncBadID(t *testing.T) {
+ HandleFunc("miek.nl.", HelloServerBadID)
defer HandleRemove("miek.nl.")
s, addrstr, err := RunLocalUDPServer("127.0.0.1:0")
@@ -450,3 +451,61 @@ func TestTimeout(t *testing.T) {
t.Errorf("exchange took longer (%v) than specified Timeout (%v)", length, timeout)
}
}
+
+// Check that responses from deduplicated requests aren't shared between callers
+func TestConcurrentExchanges(t *testing.T) {
+ cases := make([]*Msg, 2)
+ cases[0] = new(Msg)
+ cases[1] = new(Msg)
+ cases[1].Truncated = true
+ for _, m := range cases {
+ block := make(chan struct{})
+ waiting := make(chan struct{})
+
+ handler := func(w ResponseWriter, req *Msg) {
+ r := m.Copy()
+ r.SetReply(req)
+
+ waiting <- struct{}{}
+ <-block
+ w.WriteMsg(r)
+ }
+
+ HandleFunc("miek.nl.", handler)
+ defer HandleRemove("miek.nl.")
+
+ s, addrstr, err := RunLocalUDPServer("127.0.0.1:0")
+ if err != nil {
+ t.Fatalf("unable to run test server: %s", err)
+ }
+ defer s.Shutdown()
+
+ m := new(Msg)
+ m.SetQuestion("miek.nl.", TypeSRV)
+ c := &Client{
+ SingleInflight: true,
+ }
+ r := make([]*Msg, 2)
+
+ var wg sync.WaitGroup
+ wg.Add(len(r))
+ for i := 0; i < len(r); i++ {
+ go func(i int) {
+ r[i], _, _ = c.Exchange(m.Copy(), addrstr)
+ wg.Done()
+ }(i)
+ }
+ select {
+ case <-waiting:
+ case <-time.After(time.Second):
+ t.FailNow()
+ }
+ close(block)
+ wg.Wait()
+
+ if r[0] == r[1] {
+ t.Log("Got same response object, expected non-shared responses")
+ t.Fail()
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/clientconfig.go b/vendor/github.com/miekg/dns/clientconfig.go
index cfa9ad0b22..0a1f5a92c5 100644
--- a/vendor/github.com/miekg/dns/clientconfig.go
+++ b/vendor/github.com/miekg/dns/clientconfig.go
@@ -97,3 +97,35 @@ func ClientConfigFromFile(resolvconf string) (*ClientConfig, error) {
}
return c, nil
}
+
+// NameList returns all of the names that should be queried based on the
+// config. It is based off of go's net/dns name building, but it does not
+// check the length of the resulting names.
+func (c *ClientConfig) NameList(name string) []string {
+ // if this domain is already fully qualified, no append needed.
+ if IsFqdn(name) {
+ return []string{name}
+ }
+
+ // Check to see if the name has more labels than Ndots. Do this before making
+ // the domain fully qualified.
+ hasNdots := CountLabel(name) > c.Ndots
+ // Make the domain fully qualified.
+ name = Fqdn(name)
+
+ // Make a list of names based off search.
+ names := []string{}
+
+ // If name has enough dots, try that first.
+ if hasNdots {
+ names = append(names, name)
+ }
+ for _, s := range c.Search {
+ names = append(names, Fqdn(name+s))
+ }
+ // If we didn't have enough dots, try after suffixes.
+ if !hasNdots {
+ names = append(names, name)
+ }
+ return names
+}
diff --git a/vendor/github.com/miekg/dns/clientconfig_test.go b/vendor/github.com/miekg/dns/clientconfig_test.go
index 63bc5c814b..7755a8a6f6 100644
--- a/vendor/github.com/miekg/dns/clientconfig_test.go
+++ b/vendor/github.com/miekg/dns/clientconfig_test.go
@@ -48,3 +48,40 @@ func testConfig(t *testing.T, data string) {
func TestNameserver(t *testing.T) { testConfig(t, normal) }
func TestMissingFinalNewLine(t *testing.T) { testConfig(t, missingNewline) }
+
+func TestNameList(t *testing.T) {
+ cfg := ClientConfig{
+ Ndots: 1,
+ }
+ // fqdn should be only result returned
+ names := cfg.NameList("miek.nl.")
+ if len(names) != 1 {
+ t.Errorf("NameList returned != 1 names: %v", names)
+ } else if names[0] != "miek.nl." {
+ t.Errorf("NameList didn't return sent fqdn domain: %v", names[0])
+ }
+
+ cfg.Search = []string{
+ "test",
+ }
+ // Sent domain has NDots and search
+ names = cfg.NameList("miek.nl")
+ if len(names) != 2 {
+ t.Errorf("NameList returned != 2 names: %v", names)
+ } else if names[0] != "miek.nl." {
+ t.Errorf("NameList didn't return sent domain first: %v", names[0])
+ } else if names[1] != "miek.nl.test." {
+ t.Errorf("NameList didn't return search last: %v", names[1])
+ }
+
+ cfg.Ndots = 2
+ // Sent domain has less than NDots and search
+ names = cfg.NameList("miek.nl")
+ if len(names) != 2 {
+ t.Errorf("NameList returned != 2 names: %v", names)
+ } else if names[0] != "miek.nl.test." {
+ t.Errorf("NameList didn't return search first: %v", names[0])
+ } else if names[1] != "miek.nl." {
+ t.Errorf("NameList didn't return sent domain last: %v", names[1])
+ }
+}
diff --git a/vendor/github.com/miekg/dns/compress_generate.go b/vendor/github.com/miekg/dns/compress_generate.go
new file mode 100644
index 0000000000..1a301e9f39
--- /dev/null
+++ b/vendor/github.com/miekg/dns/compress_generate.go
@@ -0,0 +1,184 @@
+//+build ignore
+
+// compression_generate.go is meant to run with go generate. It will use
+// go/{importer,types} to track down all the RR struct types. Then for each type
+// it will look to see if there are (compressible) names, if so it will add that
+// type to compressionLenHelperType and comressionLenSearchType which "fake" the
+// compression so that Len() is fast.
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "go/format"
+ "go/importer"
+ "go/types"
+ "log"
+ "os"
+)
+
+var packageHdr = `
+// *** DO NOT MODIFY ***
+// AUTOGENERATED BY go generate from compress_generate.go
+
+package dns
+
+`
+
+// getTypeStruct will take a type and the package scope, and return the
+// (innermost) struct if the type is considered a RR type (currently defined as
+// those structs beginning with a RR_Header, could be redefined as implementing
+// the RR interface). The bool return value indicates if embedded structs were
+// resolved.
+func getTypeStruct(t types.Type, scope *types.Scope) (*types.Struct, bool) {
+ st, ok := t.Underlying().(*types.Struct)
+ if !ok {
+ return nil, false
+ }
+ if st.Field(0).Type() == scope.Lookup("RR_Header").Type() {
+ return st, false
+ }
+ if st.Field(0).Anonymous() {
+ st, _ := getTypeStruct(st.Field(0).Type(), scope)
+ return st, true
+ }
+ return nil, false
+}
+
+func main() {
+ // Import and type-check the package
+ pkg, err := importer.Default().Import("github.com/miekg/dns")
+ fatalIfErr(err)
+ scope := pkg.Scope()
+
+ domainTypes := map[string]bool{} // Types that have a domain name in them (either comressible or not).
+ cdomainTypes := map[string]bool{} // Types that have a compressible domain name in them (subset of domainType)
+ for _, name := range scope.Names() {
+ o := scope.Lookup(name)
+ if o == nil || !o.Exported() {
+ continue
+ }
+ st, _ := getTypeStruct(o.Type(), scope)
+ if st == nil {
+ continue
+ }
+ if name == "PrivateRR" {
+ continue
+ }
+
+ if scope.Lookup("Type"+o.Name()) == nil && o.Name() != "RFC3597" {
+ log.Fatalf("Constant Type%s does not exist.", o.Name())
+ }
+
+ for i := 1; i < st.NumFields(); i++ {
+ if _, ok := st.Field(i).Type().(*types.Slice); ok {
+ if st.Tag(i) == `dns:"domain-name"` {
+ domainTypes[o.Name()] = true
+ }
+ if st.Tag(i) == `dns:"cdomain-name"` {
+ cdomainTypes[o.Name()] = true
+ domainTypes[o.Name()] = true
+ }
+ continue
+ }
+
+ switch {
+ case st.Tag(i) == `dns:"domain-name"`:
+ domainTypes[o.Name()] = true
+ case st.Tag(i) == `dns:"cdomain-name"`:
+ cdomainTypes[o.Name()] = true
+ domainTypes[o.Name()] = true
+ }
+ }
+ }
+
+ b := &bytes.Buffer{}
+ b.WriteString(packageHdr)
+
+ // compressionLenHelperType - all types that have domain-name/cdomain-name can be used for compressing names
+
+ fmt.Fprint(b, "func compressionLenHelperType(c map[string]int, r RR) {\n")
+ fmt.Fprint(b, "switch x := r.(type) {\n")
+ for name, _ := range domainTypes {
+ o := scope.Lookup(name)
+ st, _ := getTypeStruct(o.Type(), scope)
+
+ fmt.Fprintf(b, "case *%s:\n", name)
+ for i := 1; i < st.NumFields(); i++ {
+ out := func(s string) { fmt.Fprintf(b, "compressionLenHelper(c, x.%s)\n", st.Field(i).Name()) }
+
+ if _, ok := st.Field(i).Type().(*types.Slice); ok {
+ switch st.Tag(i) {
+ case `dns:"domain-name"`:
+ fallthrough
+ case `dns:"cdomain-name"`:
+ // For HIP we need to slice over the elements in this slice.
+ fmt.Fprintf(b, `for i := range x.%s {
+ compressionLenHelper(c, x.%s[i])
+ }
+`, st.Field(i).Name(), st.Field(i).Name())
+ }
+ continue
+ }
+
+ switch {
+ case st.Tag(i) == `dns:"cdomain-name"`:
+ fallthrough
+ case st.Tag(i) == `dns:"domain-name"`:
+ out(st.Field(i).Name())
+ }
+ }
+ }
+ fmt.Fprintln(b, "}\n}\n\n")
+
+ // compressionLenSearchType - search cdomain-tags types for compressible names.
+
+ fmt.Fprint(b, "func compressionLenSearchType(c map[string]int, r RR) (int, bool) {\n")
+ fmt.Fprint(b, "switch x := r.(type) {\n")
+ for name, _ := range cdomainTypes {
+ o := scope.Lookup(name)
+ st, _ := getTypeStruct(o.Type(), scope)
+
+ fmt.Fprintf(b, "case *%s:\n", name)
+ j := 1
+ for i := 1; i < st.NumFields(); i++ {
+ out := func(s string, j int) {
+ fmt.Fprintf(b, "k%d, ok%d := compressionLenSearch(c, x.%s)\n", j, j, st.Field(i).Name())
+ }
+
+ // There are no slice types with names that can be compressed.
+
+ switch {
+ case st.Tag(i) == `dns:"cdomain-name"`:
+ out(st.Field(i).Name(), j)
+ j++
+ }
+ }
+ k := "k1"
+ ok := "ok1"
+ for i := 2; i < j; i++ {
+ k += fmt.Sprintf(" + k%d", i)
+ ok += fmt.Sprintf(" && ok%d", i)
+ }
+ fmt.Fprintf(b, "return %s, %s\n", k, ok)
+ }
+ fmt.Fprintln(b, "}\nreturn 0, false\n}\n\n")
+
+ // gofmt
+ res, err := format.Source(b.Bytes())
+ if err != nil {
+ b.WriteTo(os.Stderr)
+ log.Fatal(err)
+ }
+
+ f, err := os.Create("zcompress.go")
+ fatalIfErr(err)
+ defer f.Close()
+ f.Write(res)
+}
+
+func fatalIfErr(err error) {
+ if err != nil {
+ log.Fatal(err)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/dane.go b/vendor/github.com/miekg/dns/dane.go
index cdaa833ff2..8c4a14ef19 100644
--- a/vendor/github.com/miekg/dns/dane.go
+++ b/vendor/github.com/miekg/dns/dane.go
@@ -6,7 +6,6 @@ import (
"crypto/x509"
"encoding/hex"
"errors"
- "io"
)
// CertificateToDANE converts a certificate to a hex string as used in the TLSA or SMIMEA records.
@@ -23,20 +22,20 @@ func CertificateToDANE(selector, matchingType uint8, cert *x509.Certificate) (st
h := sha256.New()
switch selector {
case 0:
- io.WriteString(h, string(cert.Raw))
+ h.Write(cert.Raw)
return hex.EncodeToString(h.Sum(nil)), nil
case 1:
- io.WriteString(h, string(cert.RawSubjectPublicKeyInfo))
+ h.Write(cert.RawSubjectPublicKeyInfo)
return hex.EncodeToString(h.Sum(nil)), nil
}
case 2:
h := sha512.New()
switch selector {
case 0:
- io.WriteString(h, string(cert.Raw))
+ h.Write(cert.Raw)
return hex.EncodeToString(h.Sum(nil)), nil
case 1:
- io.WriteString(h, string(cert.RawSubjectPublicKeyInfo))
+ h.Write(cert.RawSubjectPublicKeyInfo)
return hex.EncodeToString(h.Sum(nil)), nil
}
}
diff --git a/vendor/github.com/miekg/dns/dns_test.go b/vendor/github.com/miekg/dns/dns_test.go
index ad68533fd5..dbfe25328f 100644
--- a/vendor/github.com/miekg/dns/dns_test.go
+++ b/vendor/github.com/miekg/dns/dns_test.go
@@ -310,6 +310,23 @@ func TestMsgLengthCompressionMalformed(t *testing.T) {
m.Len() // Should not crash.
}
+func TestMsgCompressLength2(t *testing.T) {
+ msg := new(Msg)
+ msg.Compress = true
+ msg.SetQuestion(Fqdn("bliep."), TypeANY)
+ msg.Answer = append(msg.Answer, &SRV{Hdr: RR_Header{Name: "blaat.", Rrtype: 0x21, Class: 0x1, Ttl: 0x3c}, Port: 0x4c57, Target: "foo.bar."})
+ msg.Extra = append(msg.Extra, &A{Hdr: RR_Header{Name: "foo.bar.", Rrtype: 0x1, Class: 0x1, Ttl: 0x3c}, A: net.IP{0xac, 0x11, 0x0, 0x3}})
+ predicted := msg.Len()
+ buf, err := msg.Pack()
+ if err != nil {
+ t.Error(err)
+ }
+ if predicted != len(buf) {
+ t.Errorf("predicted compressed length is wrong: predicted %s (len=%d) %d, actual %d",
+ msg.Question[0].Name, len(msg.Answer), predicted, len(buf))
+ }
+}
+
func TestToRFC3597(t *testing.T) {
a, _ := NewRR("miek.nl. IN A 10.0.1.1")
x := new(RFC3597)
diff --git a/vendor/github.com/miekg/dns/dnssec.go b/vendor/github.com/miekg/dns/dnssec.go
index f5f3fbdd89..07262011e6 100644
--- a/vendor/github.com/miekg/dns/dnssec.go
+++ b/vendor/github.com/miekg/dns/dnssec.go
@@ -43,7 +43,7 @@ const (
PRIVATEOID uint8 = 254
)
-// Map for algorithm names.
+// AlgorithmToString is a map of algorithm IDs to algorithm names.
var AlgorithmToString = map[uint8]string{
RSAMD5: "RSAMD5",
DH: "DH",
@@ -61,10 +61,10 @@ var AlgorithmToString = map[uint8]string{
PRIVATEOID: "PRIVATEOID",
}
-// Map of algorithm strings.
+// StringToAlgorithm is the reverse of AlgorithmToString.
var StringToAlgorithm = reverseInt8(AlgorithmToString)
-// Map of algorithm crypto hashes.
+// AlgorithmToHash is a map of algorithm crypto hash IDs to crypto.Hash's.
var AlgorithmToHash = map[uint8]crypto.Hash{
RSAMD5: crypto.MD5, // Deprecated in RFC 6725
RSASHA1: crypto.SHA1,
@@ -85,7 +85,7 @@ const (
SHA512 // Experimental
)
-// Map for hash names.
+// HashToString is a map of hash IDs to names.
var HashToString = map[uint8]string{
SHA1: "SHA1",
SHA256: "SHA256",
@@ -94,7 +94,7 @@ var HashToString = map[uint8]string{
SHA512: "SHA512",
}
-// Map of hash strings.
+// StringToHash is a map of names to hash IDs.
var StringToHash = reverseInt8(HashToString)
// DNSKEY flag values.
@@ -208,9 +208,6 @@ func (k *DNSKEY) ToDS(h uint8) *DS {
// "|" denotes concatenation
// DNSKEY RDATA = Flags | Protocol | Algorithm | Public Key.
- // digest buffer
- digest := append(owner, wire...) // another copy
-
var hash crypto.Hash
switch h {
case SHA1:
@@ -226,7 +223,8 @@ func (k *DNSKEY) ToDS(h uint8) *DS {
}
s := hash.New()
- s.Write(digest)
+ s.Write(owner)
+ s.Write(wire)
ds.Digest = hex.EncodeToString(s.Sum(nil))
return ds
}
@@ -297,7 +295,6 @@ func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
if err != nil {
return err
}
- signdata = append(signdata, wire...)
hash, ok := AlgorithmToHash[rr.Algorithm]
if !ok {
@@ -306,6 +303,7 @@ func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
h := hash.New()
h.Write(signdata)
+ h.Write(wire)
signature, err := sign(k, h.Sum(nil), hash, rr.Algorithm)
if err != nil {
@@ -415,7 +413,6 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
if err != nil {
return err
}
- signeddata = append(signeddata, wire...)
sigbuf := rr.sigBuf() // Get the binary signature data
if rr.Algorithm == PRIVATEDNS { // PRIVATEOID
@@ -438,6 +435,7 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
h := hash.New()
h.Write(signeddata)
+ h.Write(wire)
return rsa.VerifyPKCS1v15(pubkey, hash, h.Sum(nil), sigbuf)
case ECDSAP256SHA256, ECDSAP384SHA384:
@@ -452,6 +450,7 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
h := hash.New()
h.Write(signeddata)
+ h.Write(wire)
if ecdsa.Verify(pubkey, h.Sum(nil), r, s) {
return nil
}
diff --git a/vendor/github.com/miekg/dns/dnssec_keygen.go b/vendor/github.com/miekg/dns/dnssec_keygen.go
index 229a079370..5e4b7741a6 100644
--- a/vendor/github.com/miekg/dns/dnssec_keygen.go
+++ b/vendor/github.com/miekg/dns/dnssec_keygen.go
@@ -121,17 +121,17 @@ func (k *DNSKEY) setPublicKeyDSA(_Q, _P, _G, _Y *big.Int) bool {
// RFC 3110: Section 2. RSA Public KEY Resource Records
func exponentToBuf(_E int) []byte {
var buf []byte
- i := big.NewInt(int64(_E))
- if len(i.Bytes()) < 256 {
- buf = make([]byte, 1)
- buf[0] = uint8(len(i.Bytes()))
+ i := big.NewInt(int64(_E)).Bytes()
+ if len(i) < 256 {
+ buf = make([]byte, 1, 1+len(i))
+ buf[0] = uint8(len(i))
} else {
- buf = make([]byte, 3)
+ buf = make([]byte, 3, 3+len(i))
buf[0] = 0
- buf[1] = uint8(len(i.Bytes()) >> 8)
- buf[2] = uint8(len(i.Bytes()))
+ buf[1] = uint8(len(i) >> 8)
+ buf[2] = uint8(len(i))
}
- buf = append(buf, i.Bytes()...)
+ buf = append(buf, i...)
return buf
}
diff --git a/vendor/github.com/miekg/dns/dnssec_keyscan.go b/vendor/github.com/miekg/dns/dnssec_keyscan.go
index 9ff3a617ef..4f8d830b85 100644
--- a/vendor/github.com/miekg/dns/dnssec_keyscan.go
+++ b/vendor/github.com/miekg/dns/dnssec_keyscan.go
@@ -36,7 +36,7 @@ func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (crypto.PrivateKey, er
return nil, ErrPrivKey
}
// TODO(mg): check if the pubkey matches the private key
- algo, err := strconv.Atoi(strings.SplitN(m["algorithm"], " ", 2)[0])
+ algo, err := strconv.ParseUint(strings.SplitN(m["algorithm"], " ", 2)[0], 10, 8)
if err != nil {
return nil, ErrPrivKey
}
diff --git a/vendor/github.com/miekg/dns/edns.go b/vendor/github.com/miekg/dns/edns.go
index 465b85f37f..dbff3714cf 100644
--- a/vendor/github.com/miekg/dns/edns.go
+++ b/vendor/github.com/miekg/dns/edns.go
@@ -157,7 +157,7 @@ type EDNS0 interface {
String() string
}
-// The nsid EDNS0 option is used to retrieve a nameserver
+// EDNS0_NSID option is used to retrieve a nameserver
// identifier. When sending a request Nsid must be set to the empty string
// The identifier is an opaque string encoded as hex.
// Basic use pattern for creating an nsid option:
@@ -197,7 +197,7 @@ func (e *EDNS0_NSID) String() string { return string(e.Nsid) }
// e := new(dns.EDNS0_SUBNET)
// e.Code = dns.EDNS0SUBNET
// e.Family = 1 // 1 for IPv4 source address, 2 for IPv6
-// e.SourceNetMask = 32 // 32 for IPV4, 128 for IPv6
+// e.SourceNetmask = 32 // 32 for IPV4, 128 for IPv6
// e.SourceScope = 0
// e.Address = net.ParseIP("127.0.0.1").To4() // for IPv4
// // e.Address = net.ParseIP("2001:7b8:32a::2") // for IPV6
@@ -301,7 +301,7 @@ func (e *EDNS0_SUBNET) String() (s string) {
return
}
-// The Cookie EDNS0 option
+// The EDNS0_COOKIE option is used to add a DNS Cookie to a message.
//
// o := new(dns.OPT)
// o.Hdr.Name = "."
@@ -543,15 +543,15 @@ func (e *EDNS0_LOCAL) unpack(b []byte) error {
return nil
}
+// EDNS0_TCP_KEEPALIVE is an EDNS0 option that instructs the server to keep
+// the TCP connection alive. See RFC 7828.
type EDNS0_TCP_KEEPALIVE struct {
Code uint16 // Always EDNSTCPKEEPALIVE
Length uint16 // the value 0 if the TIMEOUT is omitted, the value 2 if it is present;
Timeout uint16 // an idle timeout value for the TCP connection, specified in units of 100 milliseconds, encoded in network byte order.
}
-func (e *EDNS0_TCP_KEEPALIVE) Option() uint16 {
- return EDNS0TCPKEEPALIVE
-}
+func (e *EDNS0_TCP_KEEPALIVE) Option() uint16 { return EDNS0TCPKEEPALIVE }
func (e *EDNS0_TCP_KEEPALIVE) pack() ([]byte, error) {
if e.Timeout != 0 && e.Length != 2 {
diff --git a/vendor/github.com/miekg/dns/idn/punycode.go b/vendor/github.com/miekg/dns/idn/punycode.go
index 7e5c263fc8..1d03bf6ae6 100644
--- a/vendor/github.com/miekg/dns/idn/punycode.go
+++ b/vendor/github.com/miekg/dns/idn/punycode.go
@@ -242,11 +242,8 @@ func encode(input []byte) []byte {
t, k, cp rune // weight and codepoint calculation
)
- s := &bytes.Buffer{}
for h := basiclen; h < fulllen; n, delta = n+1, delta+1 {
nextltr = next(b, n)
- s.Truncate(0)
- s.WriteRune(nextltr)
delta, n = delta+(nextltr-n)*rune(h+1), nextltr
for _, ltr = range b {
diff --git a/vendor/github.com/miekg/dns/msg.go b/vendor/github.com/miekg/dns/msg.go
index 0d8cc6fb3e..b5c074f05e 100644
--- a/vendor/github.com/miekg/dns/msg.go
+++ b/vendor/github.com/miekg/dns/msg.go
@@ -9,6 +9,7 @@
package dns
//go:generate go run msg_generate.go
+//go:generate go run compress_generate.go
import (
crand "crypto/rand"
@@ -16,22 +17,9 @@ import (
"math/big"
"math/rand"
"strconv"
+ "sync"
)
-func init() {
- // Initialize default math/rand source using crypto/rand to provide better
- // security without the performance trade-off.
- buf := make([]byte, 8)
- _, err := crand.Read(buf)
- if err != nil {
- // Failed to read from cryptographic source, fallback to default initial
- // seed (1) by returning early
- return
- }
- seed := binary.BigEndian.Uint64(buf)
- rand.Seed(int64(seed))
-}
-
const maxCompressionOffset = 2 << 13 // We have 14 bits for the compression pointer
var (
@@ -66,11 +54,45 @@ var (
// dns.Id = func() uint16 { return 3 }
var Id func() uint16 = id
+var (
+ idLock sync.Mutex
+ idRand *rand.Rand
+)
+
// id returns a 16 bits random number to be used as a
// message id. The random provided should be good enough.
func id() uint16 {
- id32 := rand.Uint32()
- return uint16(id32)
+ idLock.Lock()
+
+ if idRand == nil {
+ // This (partially) works around
+ // https://github.com/golang/go/issues/11833 by only
+ // seeding idRand upon the first call to id.
+
+ var seed int64
+ var buf [8]byte
+
+ if _, err := crand.Read(buf[:]); err == nil {
+ seed = int64(binary.LittleEndian.Uint64(buf[:]))
+ } else {
+ seed = rand.Int63()
+ }
+
+ idRand = rand.New(rand.NewSource(seed))
+ }
+
+ // The call to idRand.Uint32 must be within the
+ // mutex lock because *rand.Rand is not safe for
+ // concurrent use.
+ //
+ // There is no added performance overhead to calling
+ // idRand.Uint32 inside a mutex lock over just
+ // calling rand.Uint32 as the global math/rand rng
+ // is internally protected by a sync.Mutex.
+ id := uint16(idRand.Uint32())
+
+ idLock.Unlock()
+ return id
}
// MsgHdr is a a manually-unpacked version of (id, bits).
@@ -241,7 +263,9 @@ func packDomainName(s string, msg []byte, off int, compression map[string]int, c
bsFresh = true
}
// Don't try to compress '.'
- if compress && roBs[begin:] != "." {
+ // We should only compress when compress it true, but we should also still pick
+ // up names that can be used for *future* compression(s).
+ if compression != nil && roBs[begin:] != "." {
if p, ok := compression[roBs[begin:]]; !ok {
// Only offsets smaller than this can be used.
if offset < maxCompressionOffset {
@@ -303,6 +327,7 @@ End:
// UnpackDomainName unpacks a domain name into a string.
func UnpackDomainName(msg []byte, off int) (string, int, error) {
s := make([]byte, 0, 64)
+ labels := 0
off1 := 0
lenmsg := len(msg)
ptr := 0 // number of pointers followed
@@ -345,6 +370,15 @@ Loop:
}
}
}
+ // never exceed the allowed label count lenght (63)
+ if labels >= 63 {
+ return "", lenmsg, &Error{err: "name exceeds 63 labels"}
+ }
+ labels += 1
+ // never exceed the allowed doman name length (255 octets)
+ if len(s) >= 255 {
+ return "", lenmsg, &Error{err: "name exceeded allowed 255 octets"}
+ }
s = append(s, '.')
off += c
case 0xC0:
@@ -364,6 +398,9 @@ Loop:
if ptr++; ptr > 10 {
return "", lenmsg, &Error{err: "too many compression pointers"}
}
+ // pointer should guarantee that it advances and points forwards at least
+ // but the condition on previous three lines guarantees that it's
+ // at least loop-free
off = (c^0xC0)<<8 | int(c1)
default:
// 0x80 and 0x40 are reserved
@@ -710,12 +747,10 @@ func (dns *Msg) PackBuffer(buf []byte) (msg []byte, err error) {
// We need the uncompressed length here, because we first pack it and then compress it.
msg = buf
- compress := dns.Compress
- dns.Compress = false
- if packLen := dns.Len() + 1; len(msg) < packLen {
+ uncompressedLen := compressedLen(dns, false)
+ if packLen := uncompressedLen + 1; len(msg) < packLen {
msg = make([]byte, packLen)
}
- dns.Compress = compress
// Pack it in: header and then the pieces.
off := 0
@@ -868,16 +903,18 @@ func (dns *Msg) String() string {
// If dns.Compress is true compression it is taken into account. Len()
// is provided to be a faster way to get the size of the resulting packet,
// than packing it, measuring the size and discarding the buffer.
-func (dns *Msg) Len() int {
+func (dns *Msg) Len() int { return compressedLen(dns, dns.Compress) }
+
+// compressedLen returns the message length when in compressed wire format
+// when compress is true, otherwise the uncompressed length is returned.
+func compressedLen(dns *Msg, compress bool) int {
// We always return one more than needed.
l := 12 // Message header is always 12 bytes
- var compression map[string]int
- if dns.Compress {
- compression = make(map[string]int)
- }
+ compression := map[string]int{}
+
for i := 0; i < len(dns.Question); i++ {
l += dns.Question[i].len()
- if dns.Compress {
+ if compress {
compressionLenHelper(compression, dns.Question[i].Name)
}
}
@@ -886,7 +923,7 @@ func (dns *Msg) Len() int {
continue
}
l += dns.Answer[i].len()
- if dns.Compress {
+ if compress {
k, ok := compressionLenSearch(compression, dns.Answer[i].Header().Name)
if ok {
l += 1 - k
@@ -904,7 +941,7 @@ func (dns *Msg) Len() int {
continue
}
l += dns.Ns[i].len()
- if dns.Compress {
+ if compress {
k, ok := compressionLenSearch(compression, dns.Ns[i].Header().Name)
if ok {
l += 1 - k
@@ -922,7 +959,7 @@ func (dns *Msg) Len() int {
continue
}
l += dns.Extra[i].len()
- if dns.Compress {
+ if compress {
k, ok := compressionLenSearch(compression, dns.Extra[i].Header().Name)
if ok {
l += 1 - k
@@ -970,97 +1007,6 @@ func compressionLenSearch(c map[string]int, s string) (int, bool) {
return 0, false
}
-// TODO(miek): should add all types, because the all can be *used* for compression. Autogenerate from msg_generate and put in zmsg.go
-func compressionLenHelperType(c map[string]int, r RR) {
- switch x := r.(type) {
- case *NS:
- compressionLenHelper(c, x.Ns)
- case *MX:
- compressionLenHelper(c, x.Mx)
- case *CNAME:
- compressionLenHelper(c, x.Target)
- case *PTR:
- compressionLenHelper(c, x.Ptr)
- case *SOA:
- compressionLenHelper(c, x.Ns)
- compressionLenHelper(c, x.Mbox)
- case *MB:
- compressionLenHelper(c, x.Mb)
- case *MG:
- compressionLenHelper(c, x.Mg)
- case *MR:
- compressionLenHelper(c, x.Mr)
- case *MF:
- compressionLenHelper(c, x.Mf)
- case *MD:
- compressionLenHelper(c, x.Md)
- case *RT:
- compressionLenHelper(c, x.Host)
- case *RP:
- compressionLenHelper(c, x.Mbox)
- compressionLenHelper(c, x.Txt)
- case *MINFO:
- compressionLenHelper(c, x.Rmail)
- compressionLenHelper(c, x.Email)
- case *AFSDB:
- compressionLenHelper(c, x.Hostname)
- case *SRV:
- compressionLenHelper(c, x.Target)
- case *NAPTR:
- compressionLenHelper(c, x.Replacement)
- case *RRSIG:
- compressionLenHelper(c, x.SignerName)
- case *NSEC:
- compressionLenHelper(c, x.NextDomain)
- // HIP?
- }
-}
-
-// Only search on compressing these types.
-func compressionLenSearchType(c map[string]int, r RR) (int, bool) {
- switch x := r.(type) {
- case *NS:
- return compressionLenSearch(c, x.Ns)
- case *MX:
- return compressionLenSearch(c, x.Mx)
- case *CNAME:
- return compressionLenSearch(c, x.Target)
- case *DNAME:
- return compressionLenSearch(c, x.Target)
- case *PTR:
- return compressionLenSearch(c, x.Ptr)
- case *SOA:
- k, ok := compressionLenSearch(c, x.Ns)
- k1, ok1 := compressionLenSearch(c, x.Mbox)
- if !ok && !ok1 {
- return 0, false
- }
- return k + k1, true
- case *MB:
- return compressionLenSearch(c, x.Mb)
- case *MG:
- return compressionLenSearch(c, x.Mg)
- case *MR:
- return compressionLenSearch(c, x.Mr)
- case *MF:
- return compressionLenSearch(c, x.Mf)
- case *MD:
- return compressionLenSearch(c, x.Md)
- case *RT:
- return compressionLenSearch(c, x.Host)
- case *MINFO:
- k, ok := compressionLenSearch(c, x.Rmail)
- k1, ok1 := compressionLenSearch(c, x.Email)
- if !ok && !ok1 {
- return 0, false
- }
- return k + k1, true
- case *AFSDB:
- return compressionLenSearch(c, x.Hostname)
- }
- return 0, false
-}
-
// Copy returns a new RR which is a deep-copy of r.
func Copy(r RR) RR { r1 := r.copy(); return r1 }
diff --git a/vendor/github.com/miekg/dns/nsecx.go b/vendor/github.com/miekg/dns/nsecx.go
index 6f10f3e65b..51ce7f8b17 100644
--- a/vendor/github.com/miekg/dns/nsecx.go
+++ b/vendor/github.com/miekg/dns/nsecx.go
@@ -3,7 +3,6 @@ package dns
import (
"crypto/sha1"
"hash"
- "io"
"strings"
)
@@ -36,15 +35,15 @@ func HashName(label string, ha uint8, iter uint16, salt string) string {
}
// k = 0
- name = append(name, wire...)
- io.WriteString(s, string(name))
+ s.Write(name)
+ s.Write(wire)
nsec3 := s.Sum(nil)
// k > 0
for k := uint16(0); k < iter; k++ {
s.Reset()
- nsec3 = append(nsec3, wire...)
- io.WriteString(s, string(nsec3))
- nsec3 = s.Sum(nil)
+ s.Write(nsec3)
+ s.Write(wire)
+ nsec3 = s.Sum(nsec3[:0])
}
return toBase32(nsec3)
}
diff --git a/vendor/github.com/miekg/dns/parse_test.go b/vendor/github.com/miekg/dns/parse_test.go
index dc18b59ceb..c727c1301f 100644
--- a/vendor/github.com/miekg/dns/parse_test.go
+++ b/vendor/github.com/miekg/dns/parse_test.go
@@ -836,11 +836,7 @@ func TestSRVPacking(t *testing.T) {
if err != nil {
continue
}
- port := 8484
- tmp, err := strconv.Atoi(p)
- if err == nil {
- port = tmp
- }
+ port, _ := strconv.ParseUint(p, 10, 16)
rr := &SRV{
Hdr: RR_Header{Name: "somename.",
diff --git a/vendor/github.com/miekg/dns/reverse.go b/vendor/github.com/miekg/dns/reverse.go
index 099dac9486..f6e7a47a6e 100644
--- a/vendor/github.com/miekg/dns/reverse.go
+++ b/vendor/github.com/miekg/dns/reverse.go
@@ -6,10 +6,10 @@ var StringToType = reverseInt16(TypeToString)
// StringToClass is the reverse of ClassToString, needed for string parsing.
var StringToClass = reverseInt16(ClassToString)
-// Map of opcodes strings.
+// StringToOpcode is a map of opcodes to strings.
var StringToOpcode = reverseInt(OpcodeToString)
-// Map of rcodes strings.
+// StringToRcode is a map of rcodes to strings.
var StringToRcode = reverseInt(RcodeToString)
// Reverse a map
diff --git a/vendor/github.com/miekg/dns/scan.go b/vendor/github.com/miekg/dns/scan.go
index d34597ba34..de0db32f8d 100644
--- a/vendor/github.com/miekg/dns/scan.go
+++ b/vendor/github.com/miekg/dns/scan.go
@@ -819,8 +819,8 @@ func classToInt(token string) (uint16, bool) {
if len(token) < offset+1 {
return 0, false
}
- class, ok := strconv.Atoi(token[offset:])
- if ok != nil || class > maxUint16 {
+ class, err := strconv.ParseUint(token[offset:], 10, 16)
+ if err != nil {
return 0, false
}
return uint16(class), true
@@ -832,8 +832,8 @@ func typeToInt(token string) (uint16, bool) {
if len(token) < offset+1 {
return 0, false
}
- typ, ok := strconv.Atoi(token[offset:])
- if ok != nil || typ > maxUint16 {
+ typ, err := strconv.ParseUint(token[offset:], 10, 16)
+ if err != nil {
return 0, false
}
return uint16(typ), true
diff --git a/vendor/github.com/miekg/dns/scan_rr.go b/vendor/github.com/miekg/dns/scan_rr.go
index 8d6a1bf24a..f4c0d37675 100644
--- a/vendor/github.com/miekg/dns/scan_rr.go
+++ b/vendor/github.com/miekg/dns/scan_rr.go
@@ -447,7 +447,7 @@ func setMX(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
if l.length == 0 {
return rr, nil, ""
}
- i, e := strconv.Atoi(l.token)
+ i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return nil, &ParseError{f, "bad MX Pref", l}, ""
}
@@ -476,7 +476,7 @@ func setRT(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
if l.length == 0 {
return rr, nil, ""
}
- i, e := strconv.Atoi(l.token)
+ i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil {
return nil, &ParseError{f, "bad RT Preference", l}, ""
}
@@ -506,7 +506,7 @@ func setAFSDB(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
if l.length == 0 {
return rr, nil, ""
}
- i, e := strconv.Atoi(l.token)
+ i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return nil, &ParseError{f, "bad AFSDB Subtype", l}, ""
}
@@ -551,7 +551,7 @@ func setKX(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
if l.length == 0 {
return rr, nil, ""
}
- i, e := strconv.Atoi(l.token)
+ i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return nil, &ParseError{f, "bad KX Pref", l}, ""
}
@@ -665,7 +665,7 @@ func setSOA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
if l.err {
return nil, &ParseError{f, "bad SOA zone parameter", l}, ""
}
- if j, e := strconv.Atoi(l.token); e != nil {
+ if j, e := strconv.ParseUint(l.token, 10, 32); e != nil {
if i == 0 {
// Serial should be a number
return nil, &ParseError{f, "bad SOA zone parameter", l}, ""
@@ -705,21 +705,21 @@ func setSRV(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
if l.length == 0 {
return rr, nil, ""
}
- i, e := strconv.Atoi(l.token)
+ i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return nil, &ParseError{f, "bad SRV Priority", l}, ""
}
rr.Priority = uint16(i)
<-c // zBlank
l = <-c // zString
- i, e = strconv.Atoi(l.token)
+ i, e = strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return nil, &ParseError{f, "bad SRV Weight", l}, ""
}
rr.Weight = uint16(i)
<-c // zBlank
l = <-c // zString
- i, e = strconv.Atoi(l.token)
+ i, e = strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return nil, &ParseError{f, "bad SRV Port", l}, ""
}
@@ -749,14 +749,14 @@ func setNAPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
if l.length == 0 {
return rr, nil, ""
}
- i, e := strconv.Atoi(l.token)
+ i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return nil, &ParseError{f, "bad NAPTR Order", l}, ""
}
rr.Order = uint16(i)
<-c // zBlank
l = <-c // zString
- i, e = strconv.Atoi(l.token)
+ i, e = strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return nil, &ParseError{f, "bad NAPTR Preference", l}, ""
}
@@ -885,7 +885,7 @@ func setLOC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
if l.length == 0 {
return rr, nil, ""
}
- i, e := strconv.Atoi(l.token)
+ i, e := strconv.ParseUint(l.token, 10, 32)
if e != nil || l.err {
return nil, &ParseError{f, "bad LOC Latitude", l}, ""
}
@@ -897,7 +897,7 @@ func setLOC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
if rr.Latitude, ok = locCheckNorth(l.token, rr.Latitude); ok {
goto East
}
- i, e = strconv.Atoi(l.token)
+ i, e = strconv.ParseUint(l.token, 10, 32)
if e != nil || l.err {
return nil, &ParseError{f, "bad LOC Latitude minutes", l}, ""
}
@@ -923,7 +923,7 @@ East:
// East
<-c // zBlank
l = <-c
- if i, e := strconv.Atoi(l.token); e != nil || l.err {
+ if i, e := strconv.ParseUint(l.token, 10, 32); e != nil || l.err {
return nil, &ParseError{f, "bad LOC Longitude", l}, ""
} else {
rr.Longitude = 1000 * 60 * 60 * uint32(i)
@@ -934,7 +934,7 @@ East:
if rr.Longitude, ok = locCheckEast(l.token, rr.Longitude); ok {
goto Altitude
}
- if i, e := strconv.Atoi(l.token); e != nil || l.err {
+ if i, e := strconv.ParseUint(l.token, 10, 32); e != nil || l.err {
return nil, &ParseError{f, "bad LOC Longitude minutes", l}, ""
} else {
rr.Longitude += 1000 * 60 * uint32(i)
@@ -1016,7 +1016,7 @@ func setHIP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
if l.length == 0 {
return rr, nil, l.comment
}
- i, e := strconv.Atoi(l.token)
+ i, e := strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return nil, &ParseError{f, "bad HIP PublicKeyAlgorithm", l}, ""
}
@@ -1077,14 +1077,14 @@ func setCERT(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
}
if v, ok := StringToCertType[l.token]; ok {
rr.Type = v
- } else if i, e := strconv.Atoi(l.token); e != nil {
+ } else if i, e := strconv.ParseUint(l.token, 10, 16); e != nil {
return nil, &ParseError{f, "bad CERT Type", l}, ""
} else {
rr.Type = uint16(i)
}
<-c // zBlank
l = <-c // zString
- i, e := strconv.Atoi(l.token)
+ i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return nil, &ParseError{f, "bad CERT KeyTag", l}, ""
}
@@ -1093,7 +1093,7 @@ func setCERT(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
l = <-c // zString
if v, ok := StringToAlgorithm[l.token]; ok {
rr.Algorithm = v
- } else if i, e := strconv.Atoi(l.token); e != nil {
+ } else if i, e := strconv.ParseUint(l.token, 10, 8); e != nil {
return nil, &ParseError{f, "bad CERT Algorithm", l}, ""
} else {
rr.Algorithm = uint8(i)
@@ -1148,21 +1148,21 @@ func setRRSIG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
}
<-c // zBlank
l = <-c
- i, err := strconv.Atoi(l.token)
+ i, err := strconv.ParseUint(l.token, 10, 8)
if err != nil || l.err {
return nil, &ParseError{f, "bad RRSIG Algorithm", l}, ""
}
rr.Algorithm = uint8(i)
<-c // zBlank
l = <-c
- i, err = strconv.Atoi(l.token)
+ i, err = strconv.ParseUint(l.token, 10, 8)
if err != nil || l.err {
return nil, &ParseError{f, "bad RRSIG Labels", l}, ""
}
rr.Labels = uint8(i)
<-c // zBlank
l = <-c
- i, err = strconv.Atoi(l.token)
+ i, err = strconv.ParseUint(l.token, 10, 32)
if err != nil || l.err {
return nil, &ParseError{f, "bad RRSIG OrigTtl", l}, ""
}
@@ -1193,7 +1193,7 @@ func setRRSIG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
}
<-c // zBlank
l = <-c
- i, err = strconv.Atoi(l.token)
+ i, err = strconv.ParseUint(l.token, 10, 16)
if err != nil || l.err {
return nil, &ParseError{f, "bad RRSIG KeyTag", l}, ""
}
@@ -1274,21 +1274,21 @@ func setNSEC3(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
if l.length == 0 {
return rr, nil, l.comment
}
- i, e := strconv.Atoi(l.token)
+ i, e := strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return nil, &ParseError{f, "bad NSEC3 Hash", l}, ""
}
rr.Hash = uint8(i)
<-c // zBlank
l = <-c
- i, e = strconv.Atoi(l.token)
+ i, e = strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return nil, &ParseError{f, "bad NSEC3 Flags", l}, ""
}
rr.Flags = uint8(i)
<-c // zBlank
l = <-c
- i, e = strconv.Atoi(l.token)
+ i, e = strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return nil, &ParseError{f, "bad NSEC3 Iterations", l}, ""
}
@@ -1342,21 +1342,21 @@ func setNSEC3PARAM(h RR_Header, c chan lex, o, f string) (RR, *ParseError, strin
if l.length == 0 {
return rr, nil, ""
}
- i, e := strconv.Atoi(l.token)
+ i, e := strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return nil, &ParseError{f, "bad NSEC3PARAM Hash", l}, ""
}
rr.Hash = uint8(i)
<-c // zBlank
l = <-c
- i, e = strconv.Atoi(l.token)
+ i, e = strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return nil, &ParseError{f, "bad NSEC3PARAM Flags", l}, ""
}
rr.Flags = uint8(i)
<-c // zBlank
l = <-c
- i, e = strconv.Atoi(l.token)
+ i, e = strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return nil, &ParseError{f, "bad NSEC3PARAM Iterations", l}, ""
}
@@ -1440,14 +1440,14 @@ func setSSHFP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
if l.length == 0 {
return rr, nil, ""
}
- i, e := strconv.Atoi(l.token)
+ i, e := strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return nil, &ParseError{f, "bad SSHFP Algorithm", l}, ""
}
rr.Algorithm = uint8(i)
<-c // zBlank
l = <-c
- i, e = strconv.Atoi(l.token)
+ i, e = strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return nil, &ParseError{f, "bad SSHFP Type", l}, ""
}
@@ -1469,21 +1469,21 @@ func setDNSKEYs(h RR_Header, c chan lex, o, f, typ string) (RR, *ParseError, str
if l.length == 0 {
return rr, nil, l.comment
}
- i, e := strconv.Atoi(l.token)
+ i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return nil, &ParseError{f, "bad " + typ + " Flags", l}, ""
}
rr.Flags = uint16(i)
<-c // zBlank
l = <-c // zString
- i, e = strconv.Atoi(l.token)
+ i, e = strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return nil, &ParseError{f, "bad " + typ + " Protocol", l}, ""
}
rr.Protocol = uint8(i)
<-c // zBlank
l = <-c // zString
- i, e = strconv.Atoi(l.token)
+ i, e = strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return nil, &ParseError{f, "bad " + typ + " Algorithm", l}, ""
}
@@ -1525,21 +1525,21 @@ func setRKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
if l.length == 0 {
return rr, nil, l.comment
}
- i, e := strconv.Atoi(l.token)
+ i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return nil, &ParseError{f, "bad RKEY Flags", l}, ""
}
rr.Flags = uint16(i)
<-c // zBlank
l = <-c // zString
- i, e = strconv.Atoi(l.token)
+ i, e = strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return nil, &ParseError{f, "bad RKEY Protocol", l}, ""
}
rr.Protocol = uint8(i)
<-c // zBlank
l = <-c // zString
- i, e = strconv.Atoi(l.token)
+ i, e = strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return nil, &ParseError{f, "bad RKEY Algorithm", l}, ""
}
@@ -1610,14 +1610,14 @@ func setDSs(h RR_Header, c chan lex, o, f, typ string) (RR, *ParseError, string)
if l.length == 0 {
return rr, nil, l.comment
}
- i, e := strconv.Atoi(l.token)
+ i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return nil, &ParseError{f, "bad " + typ + " KeyTag", l}, ""
}
rr.KeyTag = uint16(i)
<-c // zBlank
l = <-c
- if i, e := strconv.Atoi(l.token); e != nil {
+ if i, e = strconv.ParseUint(l.token, 10, 8); e != nil {
i, ok := StringToAlgorithm[l.tokenUpper]
if !ok || l.err {
return nil, &ParseError{f, "bad " + typ + " Algorithm", l}, ""
@@ -1628,7 +1628,7 @@ func setDSs(h RR_Header, c chan lex, o, f, typ string) (RR, *ParseError, string)
}
<-c // zBlank
l = <-c
- i, e = strconv.Atoi(l.token)
+ i, e = strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return nil, &ParseError{f, "bad " + typ + " DigestType", l}, ""
}
@@ -1669,14 +1669,14 @@ func setTA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
if l.length == 0 {
return rr, nil, l.comment
}
- i, e := strconv.Atoi(l.token)
+ i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return nil, &ParseError{f, "bad TA KeyTag", l}, ""
}
rr.KeyTag = uint16(i)
<-c // zBlank
l = <-c
- if i, e := strconv.Atoi(l.token); e != nil {
+ if i, e := strconv.ParseUint(l.token, 10, 8); e != nil {
i, ok := StringToAlgorithm[l.tokenUpper]
if !ok || l.err {
return nil, &ParseError{f, "bad TA Algorithm", l}, ""
@@ -1687,7 +1687,7 @@ func setTA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
}
<-c // zBlank
l = <-c
- i, e = strconv.Atoi(l.token)
+ i, e = strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return nil, &ParseError{f, "bad TA DigestType", l}, ""
}
@@ -1707,21 +1707,21 @@ func setTLSA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
if l.length == 0 {
return rr, nil, l.comment
}
- i, e := strconv.Atoi(l.token)
+ i, e := strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return nil, &ParseError{f, "bad TLSA Usage", l}, ""
}
rr.Usage = uint8(i)
<-c // zBlank
l = <-c
- i, e = strconv.Atoi(l.token)
+ i, e = strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return nil, &ParseError{f, "bad TLSA Selector", l}, ""
}
rr.Selector = uint8(i)
<-c // zBlank
l = <-c
- i, e = strconv.Atoi(l.token)
+ i, e = strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return nil, &ParseError{f, "bad TLSA MatchingType", l}, ""
}
@@ -1742,21 +1742,21 @@ func setSMIMEA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
if l.length == 0 {
return rr, nil, l.comment
}
- i, e := strconv.Atoi(l.token)
+ i, e := strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return nil, &ParseError{f, "bad SMIMEA Usage", l}, ""
}
rr.Usage = uint8(i)
<-c // zBlank
l = <-c
- i, e = strconv.Atoi(l.token)
+ i, e = strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return nil, &ParseError{f, "bad SMIMEA Selector", l}, ""
}
rr.Selector = uint8(i)
<-c // zBlank
l = <-c
- i, e = strconv.Atoi(l.token)
+ i, e = strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return nil, &ParseError{f, "bad SMIMEA MatchingType", l}, ""
}
@@ -1842,14 +1842,14 @@ func setURI(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
return rr, nil, ""
}
- i, e := strconv.Atoi(l.token)
+ i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return nil, &ParseError{f, "bad URI Priority", l}, ""
}
rr.Priority = uint16(i)
<-c // zBlank
l = <-c
- i, e = strconv.Atoi(l.token)
+ i, e = strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return nil, &ParseError{f, "bad URI Weight", l}, ""
}
@@ -1888,7 +1888,7 @@ func setNID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
if l.length == 0 {
return rr, nil, ""
}
- i, e := strconv.Atoi(l.token)
+ i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return nil, &ParseError{f, "bad NID Preference", l}, ""
}
@@ -1911,7 +1911,7 @@ func setL32(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
if l.length == 0 {
return rr, nil, ""
}
- i, e := strconv.Atoi(l.token)
+ i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return nil, &ParseError{f, "bad L32 Preference", l}, ""
}
@@ -1933,7 +1933,7 @@ func setLP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
if l.length == 0 {
return rr, nil, ""
}
- i, e := strconv.Atoi(l.token)
+ i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return nil, &ParseError{f, "bad LP Preference", l}, ""
}
@@ -1966,7 +1966,7 @@ func setL64(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
if l.length == 0 {
return rr, nil, ""
}
- i, e := strconv.Atoi(l.token)
+ i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return nil, &ParseError{f, "bad L64 Preference", l}, ""
}
@@ -1988,7 +1988,7 @@ func setUID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
if l.length == 0 {
return rr, nil, ""
}
- i, e := strconv.Atoi(l.token)
+ i, e := strconv.ParseUint(l.token, 10, 32)
if e != nil || l.err {
return nil, &ParseError{f, "bad UID Uid", l}, ""
}
@@ -2003,7 +2003,7 @@ func setGID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
if l.length == 0 {
return rr, nil, ""
}
- i, e := strconv.Atoi(l.token)
+ i, e := strconv.ParseUint(l.token, 10, 32)
if e != nil || l.err {
return nil, &ParseError{f, "bad GID Gid", l}, ""
}
@@ -2033,7 +2033,7 @@ func setPX(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
if l.length == 0 {
return rr, nil, ""
}
- i, e := strconv.Atoi(l.token)
+ i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return nil, &ParseError{f, "bad PX Preference", l}, ""
}
@@ -2079,7 +2079,7 @@ func setCAA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
if l.length == 0 {
return rr, nil, l.comment
}
- i, err := strconv.Atoi(l.token)
+ i, err := strconv.ParseUint(l.token, 10, 8)
if err != nil || l.err {
return nil, &ParseError{f, "bad CAA Flag", l}, ""
}
diff --git a/vendor/github.com/miekg/dns/server_test.go b/vendor/github.com/miekg/dns/server_test.go
index 098be2ebeb..f17a2f90f7 100644
--- a/vendor/github.com/miekg/dns/server_test.go
+++ b/vendor/github.com/miekg/dns/server_test.go
@@ -20,7 +20,7 @@ func HelloServer(w ResponseWriter, req *Msg) {
w.WriteMsg(m)
}
-func HelloServerBadId(w ResponseWriter, req *Msg) {
+func HelloServerBadID(w ResponseWriter, req *Msg) {
m := new(Msg)
m.SetReply(req)
m.Id++
@@ -548,7 +548,7 @@ func TestHandlerCloseTCP(t *testing.T) {
return
}
time.Sleep(time.Second / 10)
- tries += 1
+ tries++
goto exchange
}
}()
diff --git a/vendor/github.com/miekg/dns/sig0.go b/vendor/github.com/miekg/dns/sig0.go
index 2dce06af82..f31e9e6843 100644
--- a/vendor/github.com/miekg/dns/sig0.go
+++ b/vendor/github.com/miekg/dns/sig0.go
@@ -60,16 +60,15 @@ func (rr *SIG) Sign(k crypto.Signer, m *Msg) ([]byte, error) {
}
rr.Signature = toBase64(signature)
- sig := string(signature)
- buf = append(buf, sig...)
+ buf = append(buf, signature...)
if len(buf) > int(^uint16(0)) {
return nil, ErrBuf
}
// Adjust sig data length
rdoff := len(mbuf) + 1 + 2 + 2 + 4
rdlen := binary.BigEndian.Uint16(buf[rdoff:])
- rdlen += uint16(len(sig))
+ rdlen += uint16(len(signature))
binary.BigEndian.PutUint16(buf[rdoff:], rdlen)
// Adjust additional count
adc := binary.BigEndian.Uint16(buf[10:])
diff --git a/vendor/github.com/miekg/dns/smimea.go b/vendor/github.com/miekg/dns/smimea.go
index 3a4bb57003..4e7ded4b38 100644
--- a/vendor/github.com/miekg/dns/smimea.go
+++ b/vendor/github.com/miekg/dns/smimea.go
@@ -33,15 +33,15 @@ func (r *SMIMEA) Verify(cert *x509.Certificate) error {
return ErrSig // ErrSig, really?
}
-// SIMEAName returns the ownername of a SMIMEA resource record as per the
+// SMIMEAName returns the ownername of a SMIMEA resource record as per the
// format specified in RFC 'draft-ietf-dane-smime-12' Section 2 and 3
-func SMIMEAName(email_address string, domain_name string) (string, error) {
+func SMIMEAName(email, domain string) (string, error) {
hasher := sha256.New()
- hasher.Write([]byte(email_address))
+ hasher.Write([]byte(email))
// RFC Section 3: "The local-part is hashed using the SHA2-256
// algorithm with the hash truncated to 28 octets and
// represented in its hexadecimal representation to become the
// left-most label in the prepared domain name"
- return hex.EncodeToString(hasher.Sum(nil)[:28]) + "." + "_smimecert." + domain_name, nil
+ return hex.EncodeToString(hasher.Sum(nil)[:28]) + "." + "_smimecert." + domain, nil
}
diff --git a/vendor/github.com/miekg/dns/tsig.go b/vendor/github.com/miekg/dns/tsig.go
index 78365e1c5b..24013096b0 100644
--- a/vendor/github.com/miekg/dns/tsig.go
+++ b/vendor/github.com/miekg/dns/tsig.go
@@ -9,7 +9,6 @@ import (
"encoding/binary"
"encoding/hex"
"hash"
- "io"
"strconv"
"strings"
"time"
@@ -124,7 +123,7 @@ func TsigGenerate(m *Msg, secret, requestMAC string, timersOnly bool) ([]byte, s
default:
return nil, "", ErrKeyAlg
}
- io.WriteString(h, string(buf))
+ h.Write(buf)
t.MAC = hex.EncodeToString(h.Sum(nil))
t.MACSize = uint16(len(t.MAC) / 2) // Size is half!
diff --git a/vendor/github.com/miekg/dns/types.go b/vendor/github.com/miekg/dns/types.go
index c8b3191e5a..c17251cb6e 100644
--- a/vendor/github.com/miekg/dns/types.go
+++ b/vendor/github.com/miekg/dns/types.go
@@ -144,7 +144,7 @@ const (
OpcodeUpdate = 5
)
-// Headers is the wire format for the DNS packet header.
+// Header is the wire format for the DNS packet header.
type Header struct {
Id uint16
Bits uint16
diff --git a/vendor/github.com/miekg/dns/types_generate.go b/vendor/github.com/miekg/dns/types_generate.go
index bf80da329c..dd1310942b 100644
--- a/vendor/github.com/miekg/dns/types_generate.go
+++ b/vendor/github.com/miekg/dns/types_generate.go
@@ -197,7 +197,7 @@ func main() {
case st.Tag(i) == "":
switch st.Field(i).Type().(*types.Basic).Kind() {
case types.Uint8:
- o("l += 1 // %s\n")
+ o("l++ // %s\n")
case types.Uint16:
o("l += 2 // %s\n")
case types.Uint32:
diff --git a/vendor/github.com/miekg/dns/udp.go b/vendor/github.com/miekg/dns/udp.go
index c79c6c8837..af111b9a89 100644
--- a/vendor/github.com/miekg/dns/udp.go
+++ b/vendor/github.com/miekg/dns/udp.go
@@ -1,10 +1,9 @@
-// +build !windows,!plan9
+// +build !windows
package dns
import (
"net"
- "syscall"
)
// SessionUDP holds the remote address and the associated
@@ -17,29 +16,6 @@ type SessionUDP struct {
// RemoteAddr returns the remote network address.
func (s *SessionUDP) RemoteAddr() net.Addr { return s.raddr }
-// setUDPSocketOptions sets the UDP socket options.
-// This function is implemented on a per platform basis. See udp_*.go for more details
-func setUDPSocketOptions(conn *net.UDPConn) error {
- sa, err := getUDPSocketName(conn)
- if err != nil {
- return err
- }
- switch sa.(type) {
- case *syscall.SockaddrInet6:
- v6only, err := getUDPSocketOptions6Only(conn)
- if err != nil {
- return err
- }
- setUDPSocketOptions6(conn)
- if !v6only {
- setUDPSocketOptions4(conn)
- }
- case *syscall.SockaddrInet4:
- setUDPSocketOptions4(conn)
- }
- return nil
-}
-
// ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a
// net.UDPAddr.
func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
diff --git a/vendor/github.com/miekg/dns/udp_linux.go b/vendor/github.com/miekg/dns/udp_linux.go
index 142a80073e..033df42399 100644
--- a/vendor/github.com/miekg/dns/udp_linux.go
+++ b/vendor/github.com/miekg/dns/udp_linux.go
@@ -1,4 +1,4 @@
-// +build linux
+// +build linux,!appengine
package dns
@@ -15,6 +15,29 @@ import (
"syscall"
)
+// setUDPSocketOptions sets the UDP socket options.
+// This function is implemented on a per platform basis. See udp_*.go for more details
+func setUDPSocketOptions(conn *net.UDPConn) error {
+ sa, err := getUDPSocketName(conn)
+ if err != nil {
+ return err
+ }
+ switch sa.(type) {
+ case *syscall.SockaddrInet6:
+ v6only, err := getUDPSocketOptions6Only(conn)
+ if err != nil {
+ return err
+ }
+ setUDPSocketOptions6(conn)
+ if !v6only {
+ setUDPSocketOptions4(conn)
+ }
+ case *syscall.SockaddrInet4:
+ setUDPSocketOptions4(conn)
+ }
+ return nil
+}
+
// setUDPSocketOptions4 prepares the v4 socket for sessions.
func setUDPSocketOptions4(conn *net.UDPConn) error {
file, err := conn.File()
diff --git a/vendor/github.com/miekg/dns/udp_other.go b/vendor/github.com/miekg/dns/udp_other.go
index d40732441b..488a282b26 100644
--- a/vendor/github.com/miekg/dns/udp_other.go
+++ b/vendor/github.com/miekg/dns/udp_other.go
@@ -1,17 +1,15 @@
-// +build !linux,!plan9
+// +build !linux appengine
package dns
import (
"net"
- "syscall"
)
// These do nothing. See udp_linux.go for an example of how to implement this.
// We tried to adhire to some kind of naming scheme.
-
+func setUDPSocketOptions(conn *net.UDPConn) error { return nil }
func setUDPSocketOptions4(conn *net.UDPConn) error { return nil }
func setUDPSocketOptions6(conn *net.UDPConn) error { return nil }
func getUDPSocketOptions6Only(conn *net.UDPConn) (bool, error) { return false, nil }
-func getUDPSocketName(conn *net.UDPConn) (syscall.Sockaddr, error) { return nil, nil }
diff --git a/vendor/github.com/miekg/dns/udp_plan9.go b/vendor/github.com/miekg/dns/udp_plan9.go
deleted file mode 100644
index b794deeba0..0000000000
--- a/vendor/github.com/miekg/dns/udp_plan9.go
+++ /dev/null
@@ -1,34 +0,0 @@
-package dns
-
-import (
- "net"
-)
-
-func setUDPSocketOptions(conn *net.UDPConn) error { return nil }
-
-// SessionUDP holds the remote address and the associated
-// out-of-band data.
-type SessionUDP struct {
- raddr *net.UDPAddr
- context []byte
-}
-
-// RemoteAddr returns the remote network address.
-func (s *SessionUDP) RemoteAddr() net.Addr { return s.raddr }
-
-// ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a
-// net.UDPAddr.
-func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
- oob := make([]byte, 40)
- n, oobn, _, raddr, err := conn.ReadMsgUDP(b, oob)
- if err != nil {
- return n, nil, err
- }
- return n, &SessionUDP{raddr, oob[:oobn]}, err
-}
-
-// WriteToSessionUDP acts just like net.UDPConn.WritetTo(), but uses a *SessionUDP instead of a net.Addr.
-func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error) {
- n, _, err := conn.WriteMsgUDP(b, session.context, session.raddr)
- return n, err
-}
diff --git a/vendor/github.com/miekg/dns/udp_windows.go b/vendor/github.com/miekg/dns/udp_windows.go
index 2ce4b33002..51e532ac2a 100644
--- a/vendor/github.com/miekg/dns/udp_windows.go
+++ b/vendor/github.com/miekg/dns/udp_windows.go
@@ -8,6 +8,8 @@ type SessionUDP struct {
raddr *net.UDPAddr
}
+func (s *SessionUDP) RemoteAddr() net.Addr { return s.raddr }
+
// ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a
// net.UDPAddr.
func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
@@ -25,10 +27,3 @@ func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, e
return n, err
}
-func (s *SessionUDP) RemoteAddr() net.Addr { return s.raddr }
-
-// setUDPSocketOptions sets the UDP socket options.
-// This function is implemented on a per platform basis. See udp_*.go for more details
-func setUDPSocketOptions(conn *net.UDPConn) error {
- return nil
-}
diff --git a/vendor/github.com/miekg/dns/update_test.go b/vendor/github.com/miekg/dns/update_test.go
index 56602dfe9f..12760a1ee5 100644
--- a/vendor/github.com/miekg/dns/update_test.go
+++ b/vendor/github.com/miekg/dns/update_test.go
@@ -92,28 +92,28 @@ func TestPreReqAndRemovals(t *testing.T) {
m.Id = 1234
// Use a full set of RRs each time, so we are sure the rdata is stripped.
- rr_name1, _ := NewRR("name_used. 3600 IN A 127.0.0.1")
- rr_name2, _ := NewRR("name_not_used. 3600 IN A 127.0.0.1")
- rr_remove1, _ := NewRR("remove1. 3600 IN A 127.0.0.1")
- rr_remove2, _ := NewRR("remove2. 3600 IN A 127.0.0.1")
- rr_remove3, _ := NewRR("remove3. 3600 IN A 127.0.0.1")
- rr_insert, _ := NewRR("insert. 3600 IN A 127.0.0.1")
- rr_rrset1, _ := NewRR("rrset_used1. 3600 IN A 127.0.0.1")
- rr_rrset2, _ := NewRR("rrset_used2. 3600 IN A 127.0.0.1")
- rr_rrset3, _ := NewRR("rrset_not_used. 3600 IN A 127.0.0.1")
+ rrName1, _ := NewRR("name_used. 3600 IN A 127.0.0.1")
+ rrName2, _ := NewRR("name_not_used. 3600 IN A 127.0.0.1")
+ rrRemove1, _ := NewRR("remove1. 3600 IN A 127.0.0.1")
+ rrRemove2, _ := NewRR("remove2. 3600 IN A 127.0.0.1")
+ rrRemove3, _ := NewRR("remove3. 3600 IN A 127.0.0.1")
+ rrInsert, _ := NewRR("insert. 3600 IN A 127.0.0.1")
+ rrRrset1, _ := NewRR("rrset_used1. 3600 IN A 127.0.0.1")
+ rrRrset2, _ := NewRR("rrset_used2. 3600 IN A 127.0.0.1")
+ rrRrset3, _ := NewRR("rrset_not_used. 3600 IN A 127.0.0.1")
// Handle the prereqs.
- m.NameUsed([]RR{rr_name1})
- m.NameNotUsed([]RR{rr_name2})
- m.RRsetUsed([]RR{rr_rrset1})
- m.Used([]RR{rr_rrset2})
- m.RRsetNotUsed([]RR{rr_rrset3})
+ m.NameUsed([]RR{rrName1})
+ m.NameNotUsed([]RR{rrName2})
+ m.RRsetUsed([]RR{rrRrset1})
+ m.Used([]RR{rrRrset2})
+ m.RRsetNotUsed([]RR{rrRrset3})
// and now the updates.
- m.RemoveName([]RR{rr_remove1})
- m.RemoveRRset([]RR{rr_remove2})
- m.Remove([]RR{rr_remove3})
- m.Insert([]RR{rr_insert})
+ m.RemoveName([]RR{rrRemove1})
+ m.RemoveRRset([]RR{rrRemove2})
+ m.Remove([]RR{rrRemove3})
+ m.Insert([]RR{rrInsert})
// This test function isn't a Example function because we print these RR with tabs at the
// end and the Example function trim these, thus they never match.
diff --git a/vendor/github.com/miekg/dns/zcompress.go b/vendor/github.com/miekg/dns/zcompress.go
new file mode 100644
index 0000000000..86a31a9168
--- /dev/null
+++ b/vendor/github.com/miekg/dns/zcompress.go
@@ -0,0 +1,119 @@
+// *** DO NOT MODIFY ***
+// AUTOGENERATED BY go generate from compress_generate.go
+
+package dns
+
+func compressionLenHelperType(c map[string]int, r RR) {
+ switch x := r.(type) {
+ case *KX:
+ compressionLenHelper(c, x.Exchanger)
+ case *MX:
+ compressionLenHelper(c, x.Mx)
+ case *NSEC:
+ compressionLenHelper(c, x.NextDomain)
+ case *DNAME:
+ compressionLenHelper(c, x.Target)
+ case *HIP:
+ for i := range x.RendezvousServers {
+ compressionLenHelper(c, x.RendezvousServers[i])
+ }
+ case *CNAME:
+ compressionLenHelper(c, x.Target)
+ case *MR:
+ compressionLenHelper(c, x.Mr)
+ case *PX:
+ compressionLenHelper(c, x.Map822)
+ compressionLenHelper(c, x.Mapx400)
+ case *SIG:
+ compressionLenHelper(c, x.SignerName)
+ case *SRV:
+ compressionLenHelper(c, x.Target)
+ case *TALINK:
+ compressionLenHelper(c, x.PreviousName)
+ compressionLenHelper(c, x.NextName)
+ case *LP:
+ compressionLenHelper(c, x.Fqdn)
+ case *NAPTR:
+ compressionLenHelper(c, x.Replacement)
+ case *NS:
+ compressionLenHelper(c, x.Ns)
+ case *RP:
+ compressionLenHelper(c, x.Mbox)
+ compressionLenHelper(c, x.Txt)
+ case *RRSIG:
+ compressionLenHelper(c, x.SignerName)
+ case *TKEY:
+ compressionLenHelper(c, x.Algorithm)
+ case *TSIG:
+ compressionLenHelper(c, x.Algorithm)
+ case *AFSDB:
+ compressionLenHelper(c, x.Hostname)
+ case *MF:
+ compressionLenHelper(c, x.Mf)
+ case *RT:
+ compressionLenHelper(c, x.Host)
+ case *MINFO:
+ compressionLenHelper(c, x.Rmail)
+ compressionLenHelper(c, x.Email)
+ case *PTR:
+ compressionLenHelper(c, x.Ptr)
+ case *SOA:
+ compressionLenHelper(c, x.Ns)
+ compressionLenHelper(c, x.Mbox)
+ case *MD:
+ compressionLenHelper(c, x.Md)
+ case *NSAPPTR:
+ compressionLenHelper(c, x.Ptr)
+ case *MG:
+ compressionLenHelper(c, x.Mg)
+ case *MB:
+ compressionLenHelper(c, x.Mb)
+ }
+}
+
+func compressionLenSearchType(c map[string]int, r RR) (int, bool) {
+ switch x := r.(type) {
+ case *MF:
+ k1, ok1 := compressionLenSearch(c, x.Mf)
+ return k1, ok1
+ case *MG:
+ k1, ok1 := compressionLenSearch(c, x.Mg)
+ return k1, ok1
+ case *MINFO:
+ k1, ok1 := compressionLenSearch(c, x.Rmail)
+ k2, ok2 := compressionLenSearch(c, x.Email)
+ return k1 + k2, ok1 && ok2
+ case *MR:
+ k1, ok1 := compressionLenSearch(c, x.Mr)
+ return k1, ok1
+ case *PTR:
+ k1, ok1 := compressionLenSearch(c, x.Ptr)
+ return k1, ok1
+ case *AFSDB:
+ k1, ok1 := compressionLenSearch(c, x.Hostname)
+ return k1, ok1
+ case *CNAME:
+ k1, ok1 := compressionLenSearch(c, x.Target)
+ return k1, ok1
+ case *MD:
+ k1, ok1 := compressionLenSearch(c, x.Md)
+ return k1, ok1
+ case *RT:
+ k1, ok1 := compressionLenSearch(c, x.Host)
+ return k1, ok1
+ case *SOA:
+ k1, ok1 := compressionLenSearch(c, x.Ns)
+ k2, ok2 := compressionLenSearch(c, x.Mbox)
+ return k1 + k2, ok1 && ok2
+ case *MB:
+ k1, ok1 := compressionLenSearch(c, x.Mb)
+ return k1, ok1
+ case *MX:
+ k1, ok1 := compressionLenSearch(c, x.Mx)
+ return k1, ok1
+ case *NS:
+ k1, ok1 := compressionLenSearch(c, x.Ns)
+ return k1, ok1
+ }
+ return 0, false
+}
diff --git a/vendor/github.com/miekg/dns/ztypes.go b/vendor/github.com/miekg/dns/ztypes.go
index 3c052773e9..311b8243b7 100644
--- a/vendor/github.com/miekg/dns/ztypes.go
+++ b/vendor/github.com/miekg/dns/ztypes.go
@@ -254,7 +254,7 @@ func (rr *ANY) len() int {
}
func (rr *CAA) len() int {
l := rr.Hdr.len()
- l += 1 // Flag
+ l++ // Flag
l += len(rr.Tag) + 1
l += len(rr.Value)
return l
@@ -263,7 +263,7 @@ func (rr *CERT) len() int {
l := rr.Hdr.len()
l += 2 // Type
l += 2 // KeyTag
- l += 1 // Algorithm
+ l++ // Algorithm
l += base64.StdEncoding.DecodedLen(len(rr.Certificate))
return l
}
@@ -285,16 +285,16 @@ func (rr *DNAME) len() int {
func (rr *DNSKEY) len() int {
l := rr.Hdr.len()
l += 2 // Flags
- l += 1 // Protocol
- l += 1 // Algorithm
+ l++ // Protocol
+ l++ // Algorithm
l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
return l
}
func (rr *DS) len() int {
l := rr.Hdr.len()
l += 2 // KeyTag
- l += 1 // Algorithm
- l += 1 // DigestType
+ l++ // Algorithm
+ l++ // DigestType
l += len(rr.Digest)/2 + 1
return l
}
@@ -333,8 +333,8 @@ func (rr *HINFO) len() int {
}
func (rr *HIP) len() int {
l := rr.Hdr.len()
- l += 1 // HitLength
- l += 1 // PublicKeyAlgorithm
+ l++ // HitLength
+ l++ // PublicKeyAlgorithm
l += 2 // PublicKeyLength
l += len(rr.Hit)/2 + 1
l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
@@ -363,10 +363,10 @@ func (rr *L64) len() int {
}
func (rr *LOC) len() int {
l := rr.Hdr.len()
- l += 1 // Version
- l += 1 // Size
- l += 1 // HorizPre
- l += 1 // VertPre
+ l++ // Version
+ l++ // Size
+ l++ // HorizPre
+ l++ // VertPre
l += 4 // Latitude
l += 4 // Longitude
l += 4 // Altitude
@@ -455,10 +455,10 @@ func (rr *NSAPPTR) len() int {
}
func (rr *NSEC3PARAM) len() int {
l := rr.Hdr.len()
- l += 1 // Hash
- l += 1 // Flags
+ l++ // Hash
+ l++ // Flags
l += 2 // Iterations
- l += 1 // SaltLength
+ l++ // SaltLength
l += len(rr.Salt)/2 + 1
return l
}
@@ -487,8 +487,8 @@ func (rr *RFC3597) len() int {
func (rr *RKEY) len() int {
l := rr.Hdr.len()
l += 2 // Flags
- l += 1 // Protocol
- l += 1 // Algorithm
+ l++ // Protocol
+ l++ // Algorithm
l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
return l
}
@@ -501,8 +501,8 @@ func (rr *RP) len() int {
func (rr *RRSIG) len() int {
l := rr.Hdr.len()
l += 2 // TypeCovered
- l += 1 // Algorithm
- l += 1 // Labels
+ l++ // Algorithm
+ l++ // Labels
l += 4 // OrigTtl
l += 4 // Expiration
l += 4 // Inception
@@ -519,9 +519,9 @@ func (rr *RT) len() int {
}
func (rr *SMIMEA) len() int {
l := rr.Hdr.len()
- l += 1 // Usage
- l += 1 // Selector
- l += 1 // MatchingType
+ l++ // Usage
+ l++ // Selector
+ l++ // MatchingType
l += len(rr.Certificate)/2 + 1
return l
}
@@ -553,16 +553,16 @@ func (rr *SRV) len() int {
}
func (rr *SSHFP) len() int {
l := rr.Hdr.len()
- l += 1 // Algorithm
- l += 1 // Type
+ l++ // Algorithm
+ l++ // Type
l += len(rr.FingerPrint)/2 + 1
return l
}
func (rr *TA) len() int {
l := rr.Hdr.len()
l += 2 // KeyTag
- l += 1 // Algorithm
- l += 1 // DigestType
+ l++ // Algorithm
+ l++ // DigestType
l += len(rr.Digest)/2 + 1
return l
}
@@ -587,9 +587,9 @@ func (rr *TKEY) len() int {
}
func (rr *TLSA) len() int {
l := rr.Hdr.len()
- l += 1 // Usage
- l += 1 // Selector
- l += 1 // MatchingType
+ l++ // Usage
+ l++ // Selector
+ l++ // MatchingType
l += len(rr.Certificate)/2 + 1
return l
}
diff --git a/vendor/github.com/prometheus/client_model/AUTHORS.md b/vendor/github.com/prometheus/client_model/AUTHORS.md
deleted file mode 100644
index e8b3efa6ac..0000000000
--- a/vendor/github.com/prometheus/client_model/AUTHORS.md
+++ /dev/null
@@ -1,13 +0,0 @@
-The Prometheus project was started by Matt T. Proud (emeritus) and
-Julius Volz in 2012.
-
-Maintainers of this repository:
-
-* Björn Rabenstein
-
-The following individuals have contributed code to this repository
-(listed in alphabetical order):
-
-* Björn Rabenstein
-* Matt T. Proud
-* Tobias Schmidt
diff --git a/vendor/github.com/prometheus/client_model/CONTRIBUTING.md b/vendor/github.com/prometheus/client_model/CONTRIBUTING.md
index 573d58741b..40503edbf1 100644
--- a/vendor/github.com/prometheus/client_model/CONTRIBUTING.md
+++ b/vendor/github.com/prometheus/client_model/CONTRIBUTING.md
@@ -2,16 +2,16 @@
Prometheus uses GitHub to manage reviews of pull requests.
-* If you have a trivial fix or improvement, go ahead and create a pull
- request, addressing (with `@...`) one or more of the maintainers
- (see [AUTHORS.md](AUTHORS.md)) in the description of the pull request.
+* If you have a trivial fix or improvement, go ahead and create a pull request,
+ addressing (with `@...`) the maintainer of this repository (see
+ [MAINTAINERS.md](MAINTAINERS.md)) in the description of the pull request.
* If you plan to do something more involved, first discuss your ideas
on our [mailing list](https://groups.google.com/forum/?fromgroups#!forum/prometheus-developers).
This will avoid unnecessary work and surely give you and us a good deal
of inspiration.
-* Relevant coding style guidelines for the Go parts are the [Go Code Review
+* Relevant coding style guidelines are the [Go Code Review
Comments](https://code.google.com/p/go-wiki/wiki/CodeReviewComments)
and the _Formatting and style_ section of Peter Bourgon's [Go: Best
Practices for Production
diff --git a/vendor/github.com/prometheus/client_model/MAINTAINERS.md b/vendor/github.com/prometheus/client_model/MAINTAINERS.md
new file mode 100644
index 0000000000..3ede55fe18
--- /dev/null
+++ b/vendor/github.com/prometheus/client_model/MAINTAINERS.md
@@ -0,0 +1 @@
+* Björn Rabenstein
diff --git a/vendor/github.com/prometheus/common/AUTHORS.md b/vendor/github.com/prometheus/common/AUTHORS.md
deleted file mode 100644
index c63f4d3951..0000000000
--- a/vendor/github.com/prometheus/common/AUTHORS.md
+++ /dev/null
@@ -1,11 +0,0 @@
-Maintainers of this repository:
-
-* Fabian Reinartz
-
-The following individuals have contributed code to this repository
-(listed in alphabetical order):
-
-* Björn Rabenstein
-* Fabian Reinartz
-* Julius Volz
-* Miguel Molina
diff --git a/vendor/github.com/prometheus/common/CONTRIBUTING.md b/vendor/github.com/prometheus/common/CONTRIBUTING.md
index 5705f0fbea..40503edbf1 100644
--- a/vendor/github.com/prometheus/common/CONTRIBUTING.md
+++ b/vendor/github.com/prometheus/common/CONTRIBUTING.md
@@ -2,9 +2,9 @@
Prometheus uses GitHub to manage reviews of pull requests.
-* If you have a trivial fix or improvement, go ahead and create a pull
- request, addressing (with `@...`) one or more of the maintainers
- (see [AUTHORS.md](AUTHORS.md)) in the description of the pull request.
+* If you have a trivial fix or improvement, go ahead and create a pull request,
+ addressing (with `@...`) the maintainer of this repository (see
+ [MAINTAINERS.md](MAINTAINERS.md)) in the description of the pull request.
* If you plan to do something more involved, first discuss your ideas
on our [mailing list](https://groups.google.com/forum/?fromgroups#!forum/prometheus-developers).
diff --git a/vendor/github.com/prometheus/common/MAINTAINERS.md b/vendor/github.com/prometheus/common/MAINTAINERS.md
new file mode 100644
index 0000000000..1b31521616
--- /dev/null
+++ b/vendor/github.com/prometheus/common/MAINTAINERS.md
@@ -0,0 +1 @@
+* Fabian Reinartz
diff --git a/vendor/github.com/prometheus/common/model/value.go b/vendor/github.com/prometheus/common/model/value.go
index 7728abaeea..c9ed3ffd82 100644
--- a/vendor/github.com/prometheus/common/model/value.go
+++ b/vendor/github.com/prometheus/common/model/value.go
@@ -129,11 +129,8 @@ func (s *Sample) Equal(o *Sample) bool {
if !s.Timestamp.Equal(o.Timestamp) {
return false
}
- if s.Value.Equal(o.Value) {
- return false
- }
- return true
+ return s.Value.Equal(o.Value)
}
func (s Sample) String() string {
diff --git a/vendor/github.com/prometheus/common/model/value_test.go b/vendor/github.com/prometheus/common/model/value_test.go
index 8d2b69ea14..b97dcf84cf 100644
--- a/vendor/github.com/prometheus/common/model/value_test.go
+++ b/vendor/github.com/prometheus/common/model/value_test.go
@@ -21,7 +21,7 @@ import (
"testing"
)
-func TestEqual(t *testing.T) {
+func TestEqualValues(t *testing.T) {
tests := map[string]struct {
in1, in2 SampleValue
want bool
@@ -76,6 +76,57 @@ func TestEqual(t *testing.T) {
}
}
+func TestEqualSamples(t *testing.T) {
+ testSample := &Sample{}
+
+ tests := map[string]struct {
+ in1, in2 *Sample
+ want bool
+ }{
+ "equal pointers": {
+ in1: testSample,
+ in2: testSample,
+ want: true,
+ },
+ "different metrics": {
+ in1: &Sample{Metric: Metric{"foo": "bar"}},
+ in2: &Sample{Metric: Metric{"foo": "biz"}},
+ want: false,
+ },
+ "different timestamp": {
+ in1: &Sample{Timestamp: 0},
+ in2: &Sample{Timestamp: 1},
+ want: false,
+ },
+ "different value": {
+ in1: &Sample{Value: 0},
+ in2: &Sample{Value: 1},
+ want: false,
+ },
+ "equal samples": {
+ in1: &Sample{
+ Metric: Metric{"foo": "bar"},
+ Timestamp: 0,
+ Value: 1,
+ },
+ in2: &Sample{
+ Metric: Metric{"foo": "bar"},
+ Timestamp: 0,
+ Value: 1,
+ },
+ want: true,
+ },
+ }
+
+ for name, test := range tests {
+ got := test.in1.Equal(test.in2)
+ if got != test.want {
+ t.Errorf("Comparing %s, %v and %v: got %t, want %t", name, test.in1, test.in2, got, test.want)
+ }
+ }
+
+}
+
func TestSamplePairJSON(t *testing.T) {
input := []struct {
plain string
diff --git a/vendor/github.com/prometheus/procfs/AUTHORS.md b/vendor/github.com/prometheus/procfs/AUTHORS.md
deleted file mode 100644
index d558635602..0000000000
--- a/vendor/github.com/prometheus/procfs/AUTHORS.md
+++ /dev/null
@@ -1,21 +0,0 @@
-The Prometheus project was started by Matt T. Proud (emeritus) and
-Julius Volz in 2012.
-
-Maintainers of this repository:
-
-* Tobias Schmidt
-
-The following individuals have contributed code to this repository
-(listed in alphabetical order):
-
-* Armen Baghumian
-* Bjoern Rabenstein
-* David Cournapeau
-* Ji-Hoon, Seol
-* Jonas Große Sundrup
-* Julius Volz
-* Matt Layher
-* Matthias Rampke
-* Nicky Gerritsen
-* Rémi Audebert
-* Tobias Schmidt
diff --git a/vendor/github.com/prometheus/procfs/CONTRIBUTING.md b/vendor/github.com/prometheus/procfs/CONTRIBUTING.md
index 5705f0fbea..40503edbf1 100644
--- a/vendor/github.com/prometheus/procfs/CONTRIBUTING.md
+++ b/vendor/github.com/prometheus/procfs/CONTRIBUTING.md
@@ -2,9 +2,9 @@
Prometheus uses GitHub to manage reviews of pull requests.
-* If you have a trivial fix or improvement, go ahead and create a pull
- request, addressing (with `@...`) one or more of the maintainers
- (see [AUTHORS.md](AUTHORS.md)) in the description of the pull request.
+* If you have a trivial fix or improvement, go ahead and create a pull request,
+ addressing (with `@...`) the maintainer of this repository (see
+ [MAINTAINERS.md](MAINTAINERS.md)) in the description of the pull request.
* If you plan to do something more involved, first discuss your ideas
on our [mailing list](https://groups.google.com/forum/?fromgroups#!forum/prometheus-developers).
diff --git a/vendor/github.com/prometheus/procfs/MAINTAINERS.md b/vendor/github.com/prometheus/procfs/MAINTAINERS.md
new file mode 100644
index 0000000000..35993c41c2
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/MAINTAINERS.md
@@ -0,0 +1 @@
+* Tobias Schmidt
diff --git a/vendor/github.com/prometheus/procfs/README.md b/vendor/github.com/prometheus/procfs/README.md
index 6e7ee6b8b7..2095494719 100644
--- a/vendor/github.com/prometheus/procfs/README.md
+++ b/vendor/github.com/prometheus/procfs/README.md
@@ -8,3 +8,4 @@ backwards-incompatible ways without warnings. Use it at your own risk.
[](https://godoc.org/github.com/prometheus/procfs)
[](https://travis-ci.org/prometheus/procfs)
+[](https://goreportcard.com/report/github.com/prometheus/procfs)
diff --git a/vendor/github.com/prometheus/procfs/buddyinfo.go b/vendor/github.com/prometheus/procfs/buddyinfo.go
new file mode 100644
index 0000000000..680a9842a4
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/buddyinfo.go
@@ -0,0 +1,95 @@
+// Copyright 2017 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package procfs
+
+import (
+ "bufio"
+ "fmt"
+ "io"
+ "os"
+ "strconv"
+ "strings"
+)
+
+// A BuddyInfo is the details parsed from /proc/buddyinfo.
+// The data is comprised of an array of free fragments of each size.
+// The sizes are 2^n*PAGE_SIZE, where n is the array index.
+type BuddyInfo struct {
+ Node string
+ Zone string
+ Sizes []float64
+}
+
+// NewBuddyInfo reads the buddyinfo statistics.
+func NewBuddyInfo() ([]BuddyInfo, error) {
+ fs, err := NewFS(DefaultMountPoint)
+ if err != nil {
+ return nil, err
+ }
+
+ return fs.NewBuddyInfo()
+}
+
+// NewBuddyInfo reads the buddyinfo statistics from the specified `proc` filesystem.
+func (fs FS) NewBuddyInfo() ([]BuddyInfo, error) {
+ file, err := os.Open(fs.Path("buddyinfo"))
+ if err != nil {
+ return nil, err
+ }
+ defer file.Close()
+
+ return parseBuddyInfo(file)
+}
+
+func parseBuddyInfo(r io.Reader) ([]BuddyInfo, error) {
+ var (
+ buddyInfo = []BuddyInfo{}
+ scanner = bufio.NewScanner(r)
+ bucketCount = -1
+ )
+
+ for scanner.Scan() {
+ var err error
+ line := scanner.Text()
+ parts := strings.Fields(string(line))
+
+ if len(parts) < 4 {
+ return nil, fmt.Errorf("invalid number of fields when parsing buddyinfo")
+ }
+
+ node := strings.TrimRight(parts[1], ",")
+ zone := strings.TrimRight(parts[3], ",")
+ arraySize := len(parts[4:])
+
+ if bucketCount == -1 {
+ bucketCount = arraySize
+ } else {
+ if bucketCount != arraySize {
+ return nil, fmt.Errorf("mismatch in number of buddyinfo buckets, previous count %d, new count %d", bucketCount, arraySize)
+ }
+ }
+
+ sizes := make([]float64, arraySize)
+ for i := 0; i < arraySize; i++ {
+ sizes[i], err = strconv.ParseFloat(parts[i+4], 64)
+ if err != nil {
+ return nil, fmt.Errorf("invalid value in buddyinfo: %s", err)
+ }
+ }
+
+ buddyInfo = append(buddyInfo, BuddyInfo{node, zone, sizes})
+ }
+
+ return buddyInfo, scanner.Err()
+}
diff --git a/vendor/github.com/prometheus/procfs/buddyinfo_test.go b/vendor/github.com/prometheus/procfs/buddyinfo_test.go
new file mode 100644
index 0000000000..bcf9355cab
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/buddyinfo_test.go
@@ -0,0 +1,64 @@
+// Copyright 2017 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package procfs
+
+import (
+ "strings"
+ "testing"
+)
+
+func TestBuddyInfo(t *testing.T) {
+ buddyInfo, err := FS("fixtures/buddyinfo/valid").NewBuddyInfo()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if want, got := "DMA", buddyInfo[0].Zone; want != got {
+ t.Errorf("want Node 0, Zone %s, got %s", want, got)
+ }
+
+ if want, got := "Normal", buddyInfo[2].Zone; want != got {
+ t.Errorf("want Node 0, Zone %s, got %s", want, got)
+ }
+
+ if want, got := 4381.0, buddyInfo[2].Sizes[0]; want != got {
+ t.Errorf("want Node 0, Zone Normal %f, got %f", want, got)
+ }
+
+ if want, got := 572.0, buddyInfo[1].Sizes[1]; want != got {
+ t.Errorf("want Node 0, Zone DMA32 %f, got %f", want, got)
+ }
+}
+
+func TestBuddyInfoShort(t *testing.T) {
+ _, err := FS("fixtures/buddyinfo/short").NewBuddyInfo()
+ if err == nil {
+ t.Errorf("expected error, but none occurred")
+ }
+
+ if want, got := "invalid number of fields when parsing buddyinfo", err.Error(); want != got {
+ t.Errorf("wrong error returned, wanted %q, got %q", want, got)
+ }
+}
+
+func TestBuddyInfoSizeMismatch(t *testing.T) {
+ _, err := FS("fixtures/buddyinfo/sizemismatch").NewBuddyInfo()
+ if err == nil {
+ t.Errorf("expected error, but none occurred")
+ }
+
+ if want, got := "mismatch in number of buddyinfo buckets", err.Error(); !strings.HasPrefix(got, want) {
+ t.Errorf("wrong error returned, wanted prefix %q, got %q", want, got)
+ }
+}
diff --git a/vendor/github.com/prometheus/procfs/fixtures/buddyinfo/short/buddyinfo b/vendor/github.com/prometheus/procfs/fixtures/buddyinfo/short/buddyinfo
new file mode 100644
index 0000000000..40e71ca357
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/fixtures/buddyinfo/short/buddyinfo
@@ -0,0 +1,3 @@
+Node 0, zone
+Node 0, zone
+Node 0, zone
diff --git a/vendor/github.com/prometheus/procfs/fixtures/buddyinfo/sizemismatch/buddyinfo b/vendor/github.com/prometheus/procfs/fixtures/buddyinfo/sizemismatch/buddyinfo
new file mode 100644
index 0000000000..9456361829
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/fixtures/buddyinfo/sizemismatch/buddyinfo
@@ -0,0 +1,3 @@
+Node 0, zone DMA 1 0 1 0 2 1 1 0 1 1 3
+Node 0, zone DMA32 759 572 791 475 194 45 12 0 0 0 0 0
+Node 0, zone Normal 4381 1093 185 1530 567 102 4 0 0 0
diff --git a/vendor/github.com/prometheus/procfs/fixtures/buddyinfo/valid/buddyinfo b/vendor/github.com/prometheus/procfs/fixtures/buddyinfo/valid/buddyinfo
new file mode 100644
index 0000000000..f90594a81b
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/fixtures/buddyinfo/valid/buddyinfo
@@ -0,0 +1,3 @@
+Node 0, zone DMA 1 0 1 0 2 1 1 0 1 1 3
+Node 0, zone DMA32 759 572 791 475 194 45 12 0 0 0 0
+Node 0, zone Normal 4381 1093 185 1530 567 102 4 0 0 0 0
diff --git a/vendor/github.com/prometheus/procfs/fixtures/fs/xfs/stat b/vendor/github.com/prometheus/procfs/fixtures/fs/xfs/stat
new file mode 100644
index 0000000000..f7ca7f9407
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/fixtures/fs/xfs/stat
@@ -0,0 +1,23 @@
+extent_alloc 92447 97589 92448 93751
+abt 0 0 0 0
+blk_map 1767055 188820 184891 92447 92448 2140766 0
+bmbt 0 0 0 0
+dir 185039 92447 92444 136422
+trans 706 944304 0
+ig 185045 58807 0 126238 0 33637 22
+log 2883 113448 9 17360 739
+push_ail 945014 0 134260 15483 0 3940 464 159985 0 40
+xstrat 92447 0
+rw 107739 94045
+attr 4 0 0 0
+icluster 8677 7849 135802
+vnodes 92601 0 0 0 92444 92444 92444 0
+buf 2666287 7122 2659202 3599 2 7085 0 10297 7085
+abtb2 184941 1277345 13257 13278 0 0 0 0 0 0 0 0 0 0 2746147
+abtc2 345295 2416764 172637 172658 0 0 0 0 0 0 0 0 0 0 21406023
+bmbt2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ibt2 343004 1358467 0 0 0 0 0 0 0 0 0 0 0 0 0
+fibt2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+qm 0 0 0 0 0 0 0 0
+xpc 399724544 92823103 86219234
+debug 0
diff --git a/vendor/github.com/prometheus/procfs/fs.go b/vendor/github.com/prometheus/procfs/fs.go
index 49aaab0505..17546756b3 100644
--- a/vendor/github.com/prometheus/procfs/fs.go
+++ b/vendor/github.com/prometheus/procfs/fs.go
@@ -4,6 +4,8 @@ import (
"fmt"
"os"
"path"
+
+ "github.com/prometheus/procfs/xfs"
)
// FS represents the pseudo-filesystem proc, which provides an interface to
@@ -31,3 +33,14 @@ func NewFS(mountPoint string) (FS, error) {
func (fs FS) Path(p ...string) string {
return path.Join(append([]string{string(fs)}, p...)...)
}
+
+// XFSStats retrieves XFS filesystem runtime statistics.
+func (fs FS) XFSStats() (*xfs.Stats, error) {
+ f, err := os.Open(fs.Path("fs/xfs/stat"))
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+
+ return xfs.ParseStats(f)
+}
diff --git a/vendor/github.com/prometheus/procfs/fs_test.go b/vendor/github.com/prometheus/procfs/fs_test.go
index 91f1c6c976..e492cde55e 100644
--- a/vendor/github.com/prometheus/procfs/fs_test.go
+++ b/vendor/github.com/prometheus/procfs/fs_test.go
@@ -11,3 +11,16 @@ func TestNewFS(t *testing.T) {
t.Error("want NewFS to fail if mount point is not a directory")
}
}
+
+func TestFSXFSStats(t *testing.T) {
+ stats, err := FS("fixtures").XFSStats()
+ if err != nil {
+ t.Fatalf("failed to parse XFS stats: %v", err)
+ }
+
+ // Very lightweight test just to sanity check the path used
+ // to open XFS stats. Heavier tests in package xfs.
+ if want, got := uint32(92447), stats.ExtentAllocation.ExtentsAllocated; want != got {
+ t.Errorf("unexpected extents allocated:\nwant: %d\nhave: %d", want, got)
+ }
+}
diff --git a/vendor/github.com/prometheus/procfs/ipvs_test.go b/vendor/github.com/prometheus/procfs/ipvs_test.go
index c836c23acf..796ee5b882 100644
--- a/vendor/github.com/prometheus/procfs/ipvs_test.go
+++ b/vendor/github.com/prometheus/procfs/ipvs_test.go
@@ -14,7 +14,7 @@ var (
OutgoingBytes: 0,
}
expectedIPVSBackendStatuses = []IPVSBackendStatus{
- IPVSBackendStatus{
+ {
LocalAddress: net.ParseIP("192.168.0.22"),
LocalPort: 3306,
RemoteAddress: net.ParseIP("192.168.82.22"),
@@ -24,7 +24,7 @@ var (
ActiveConn: 248,
InactConn: 2,
},
- IPVSBackendStatus{
+ {
LocalAddress: net.ParseIP("192.168.0.22"),
LocalPort: 3306,
RemoteAddress: net.ParseIP("192.168.83.24"),
@@ -34,7 +34,7 @@ var (
ActiveConn: 248,
InactConn: 2,
},
- IPVSBackendStatus{
+ {
LocalAddress: net.ParseIP("192.168.0.22"),
LocalPort: 3306,
RemoteAddress: net.ParseIP("192.168.83.21"),
@@ -44,7 +44,7 @@ var (
ActiveConn: 248,
InactConn: 1,
},
- IPVSBackendStatus{
+ {
LocalAddress: net.ParseIP("192.168.0.57"),
LocalPort: 3306,
RemoteAddress: net.ParseIP("192.168.84.22"),
@@ -54,7 +54,7 @@ var (
ActiveConn: 0,
InactConn: 0,
},
- IPVSBackendStatus{
+ {
LocalAddress: net.ParseIP("192.168.0.57"),
LocalPort: 3306,
RemoteAddress: net.ParseIP("192.168.82.21"),
@@ -64,7 +64,7 @@ var (
ActiveConn: 1499,
InactConn: 0,
},
- IPVSBackendStatus{
+ {
LocalAddress: net.ParseIP("192.168.0.57"),
LocalPort: 3306,
RemoteAddress: net.ParseIP("192.168.50.21"),
@@ -74,7 +74,7 @@ var (
ActiveConn: 1498,
InactConn: 0,
},
- IPVSBackendStatus{
+ {
LocalAddress: net.ParseIP("192.168.0.55"),
LocalPort: 3306,
RemoteAddress: net.ParseIP("192.168.50.26"),
@@ -84,7 +84,7 @@ var (
ActiveConn: 0,
InactConn: 0,
},
- IPVSBackendStatus{
+ {
LocalAddress: net.ParseIP("192.168.0.55"),
LocalPort: 3306,
RemoteAddress: net.ParseIP("192.168.49.32"),
diff --git a/vendor/github.com/prometheus/procfs/mdstat_test.go b/vendor/github.com/prometheus/procfs/mdstat_test.go
index ca5fe4d1b0..fa463c2fb1 100644
--- a/vendor/github.com/prometheus/procfs/mdstat_test.go
+++ b/vendor/github.com/prometheus/procfs/mdstat_test.go
@@ -11,13 +11,13 @@ func TestMDStat(t *testing.T) {
}
refs := map[string]MDStat{
- "md3": MDStat{"md3", "active", 8, 8, 5853468288, 5853468288},
- "md127": MDStat{"md127", "active", 2, 2, 312319552, 312319552},
- "md0": MDStat{"md0", "active", 2, 2, 248896, 248896},
- "md4": MDStat{"md4", "inactive", 2, 2, 4883648, 4883648},
- "md6": MDStat{"md6", "active", 1, 2, 195310144, 16775552},
- "md8": MDStat{"md8", "active", 2, 2, 195310144, 16775552},
- "md7": MDStat{"md7", "active", 3, 4, 7813735424, 7813735424},
+ "md3": {"md3", "active", 8, 8, 5853468288, 5853468288},
+ "md127": {"md127", "active", 2, 2, 312319552, 312319552},
+ "md0": {"md0", "active", 2, 2, 248896, 248896},
+ "md4": {"md4", "inactive", 2, 2, 4883648, 4883648},
+ "md6": {"md6", "active", 1, 2, 195310144, 16775552},
+ "md8": {"md8", "active", 2, 2, 195310144, 16775552},
+ "md7": {"md7", "active", 3, 4, 7813735424, 7813735424},
}
if want, have := len(refs), len(mdStates); want != have {
diff --git a/vendor/github.com/prometheus/procfs/mountstats.go b/vendor/github.com/prometheus/procfs/mountstats.go
index 47ab0a7449..fe8f1f6a22 100644
--- a/vendor/github.com/prometheus/procfs/mountstats.go
+++ b/vendor/github.com/prometheus/procfs/mountstats.go
@@ -123,7 +123,7 @@ type NFSEventsStats struct {
VFSFlush uint64
// Number of times fsync() has been called on directories and files.
VFSFsync uint64
- // Number of times locking has been attemped on a file.
+ // Number of times locking has been attempted on a file.
VFSLock uint64
// Number of times files have been closed and released.
VFSFileRelease uint64
@@ -356,7 +356,7 @@ func parseMountStatsNFS(s *bufio.Scanner, statVersion string) (*MountStatsNFS, e
}
// When encountering "per-operation statistics", we must break this
- // loop and parse them seperately to ensure we can terminate parsing
+ // loop and parse them separately to ensure we can terminate parsing
// before reaching another device entry; hence why this 'if' statement
// is not just another switch case
if ss[0] == fieldPerOpStats {
diff --git a/vendor/github.com/prometheus/procfs/mountstats_test.go b/vendor/github.com/prometheus/procfs/mountstats_test.go
index e657079398..75fd4a0f1c 100644
--- a/vendor/github.com/prometheus/procfs/mountstats_test.go
+++ b/vendor/github.com/prometheus/procfs/mountstats_test.go
@@ -12,7 +12,6 @@ func TestMountStats(t *testing.T) {
tests := []struct {
name string
s string
- fs bool
mounts []*Mount
invalid bool
}{
@@ -113,7 +112,6 @@ func TestMountStats(t *testing.T) {
},
{
name: "fixtures OK",
- fs: true,
mounts: []*Mount{
{
Device: "rootfs",
@@ -201,10 +199,9 @@ func TestMountStats(t *testing.T) {
if tt.s != "" {
mounts, err = parseMountStats(strings.NewReader(tt.s))
- }
- if tt.fs {
- proc, err := FS("fixtures").NewProc(26231)
- if err != nil {
+ } else {
+ proc, e := FS("fixtures").NewProc(26231)
+ if e != nil {
t.Fatalf("failed to create proc: %v", err)
}
diff --git a/vendor/github.com/prometheus/procfs/xfs/parse.go b/vendor/github.com/prometheus/procfs/xfs/parse.go
new file mode 100644
index 0000000000..d1285fa6c6
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/xfs/parse.go
@@ -0,0 +1,361 @@
+// Copyright 2017 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package xfs
+
+import (
+ "bufio"
+ "fmt"
+ "io"
+ "log"
+ "strconv"
+ "strings"
+)
+
+// ParseStats parses a Stats from an input io.Reader, using the format
+// found in /proc/fs/xfs/stat.
+func ParseStats(r io.Reader) (*Stats, error) {
+ const (
+ // Fields parsed into stats structures.
+ fieldExtentAlloc = "extent_alloc"
+ fieldAbt = "abt"
+ fieldBlkMap = "blk_map"
+ fieldBmbt = "bmbt"
+ fieldDir = "dir"
+ fieldTrans = "trans"
+ fieldIg = "ig"
+ fieldLog = "log"
+ fieldRw = "rw"
+ fieldAttr = "attr"
+ fieldIcluster = "icluster"
+ fieldVnodes = "vnodes"
+ fieldBuf = "buf"
+ fieldXpc = "xpc"
+
+ // Unimplemented at this time due to lack of documentation.
+ fieldPushAil = "push_ail"
+ fieldXstrat = "xstrat"
+ fieldAbtb2 = "abtb2"
+ fieldAbtc2 = "abtc2"
+ fieldBmbt2 = "bmbt2"
+ fieldIbt2 = "ibt2"
+ fieldFibt2 = "fibt2"
+ fieldQm = "qm"
+ fieldDebug = "debug"
+ )
+
+ var xfss Stats
+
+ s := bufio.NewScanner(r)
+ for s.Scan() {
+ // Expect at least a string label and a single integer value, ex:
+ // - abt 0
+ // - rw 1 2
+ ss := strings.Fields(string(s.Bytes()))
+ if len(ss) < 2 {
+ continue
+ }
+ label := ss[0]
+
+ // Extended precision counters are uint64 values.
+ if label == fieldXpc {
+ us, err := parseUint64s(ss[1:])
+ if err != nil {
+ return nil, err
+ }
+
+ xfss.ExtendedPrecision, err = extendedPrecisionStats(us)
+ if err != nil {
+ return nil, err
+ }
+
+ continue
+ }
+
+ // All other counters are uint32 values.
+ us, err := parseUint32s(ss[1:])
+ if err != nil {
+ return nil, err
+ }
+
+ switch label {
+ case fieldExtentAlloc:
+ xfss.ExtentAllocation, err = extentAllocationStats(us)
+ case fieldAbt:
+ xfss.AllocationBTree, err = btreeStats(us)
+ case fieldBlkMap:
+ xfss.BlockMapping, err = blockMappingStats(us)
+ case fieldBmbt:
+ xfss.BlockMapBTree, err = btreeStats(us)
+ case fieldDir:
+ xfss.DirectoryOperation, err = directoryOperationStats(us)
+ case fieldTrans:
+ xfss.Transaction, err = transactionStats(us)
+ case fieldIg:
+ xfss.InodeOperation, err = inodeOperationStats(us)
+ case fieldLog:
+ xfss.LogOperation, err = logOperationStats(us)
+ case fieldRw:
+ xfss.ReadWrite, err = readWriteStats(us)
+ case fieldAttr:
+ xfss.AttributeOperation, err = attributeOperationStats(us)
+ case fieldIcluster:
+ xfss.InodeClustering, err = inodeClusteringStats(us)
+ case fieldVnodes:
+ xfss.Vnode, err = vnodeStats(us)
+ case fieldBuf:
+ xfss.Buffer, err = bufferStats(us)
+ }
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return &xfss, s.Err()
+}
+
+// extentAllocationStats builds an ExtentAllocationStats from a slice of uint32s.
+func extentAllocationStats(us []uint32) (ExtentAllocationStats, error) {
+ if l := len(us); l != 4 {
+ return ExtentAllocationStats{}, fmt.Errorf("incorrect number of values for XFS extent allocation stats: %d", l)
+ }
+
+ return ExtentAllocationStats{
+ ExtentsAllocated: us[0],
+ BlocksAllocated: us[1],
+ ExtentsFreed: us[2],
+ BlocksFreed: us[3],
+ }, nil
+}
+
+// btreeStats builds a BTreeStats from a slice of uint32s.
+func btreeStats(us []uint32) (BTreeStats, error) {
+ if l := len(us); l != 4 {
+ return BTreeStats{}, fmt.Errorf("incorrect number of values for XFS btree stats: %d", l)
+ }
+
+ return BTreeStats{
+ Lookups: us[0],
+ Compares: us[1],
+ RecordsInserted: us[2],
+ RecordsDeleted: us[3],
+ }, nil
+}
+
+// BlockMappingStat builds a BlockMappingStats from a slice of uint32s.
+func blockMappingStats(us []uint32) (BlockMappingStats, error) {
+ if l := len(us); l != 7 {
+ return BlockMappingStats{}, fmt.Errorf("incorrect number of values for XFS block mapping stats: %d", l)
+ }
+
+ return BlockMappingStats{
+ Reads: us[0],
+ Writes: us[1],
+ Unmaps: us[2],
+ ExtentListInsertions: us[3],
+ ExtentListDeletions: us[4],
+ ExtentListLookups: us[5],
+ ExtentListCompares: us[6],
+ }, nil
+}
+
+// DirectoryOperationStats builds a DirectoryOperationStats from a slice of uint32s.
+func directoryOperationStats(us []uint32) (DirectoryOperationStats, error) {
+ if l := len(us); l != 4 {
+ return DirectoryOperationStats{}, fmt.Errorf("incorrect number of values for XFS directory operation stats: %d", l)
+ }
+
+ return DirectoryOperationStats{
+ Lookups: us[0],
+ Creates: us[1],
+ Removes: us[2],
+ Getdents: us[3],
+ }, nil
+}
+
+// TransactionStats builds a TransactionStats from a slice of uint32s.
+func transactionStats(us []uint32) (TransactionStats, error) {
+ if l := len(us); l != 3 {
+ return TransactionStats{}, fmt.Errorf("incorrect number of values for XFS transaction stats: %d", l)
+ }
+
+ return TransactionStats{
+ Sync: us[0],
+ Async: us[1],
+ Empty: us[2],
+ }, nil
+}
+
+// InodeOperationStats builds an InodeOperationStats from a slice of uint32s.
+func inodeOperationStats(us []uint32) (InodeOperationStats, error) {
+ if l := len(us); l != 7 {
+ return InodeOperationStats{}, fmt.Errorf("incorrect number of values for XFS inode operation stats: %d", l)
+ }
+
+ return InodeOperationStats{
+ Attempts: us[0],
+ Found: us[1],
+ Recycle: us[2],
+ Missed: us[3],
+ Duplicate: us[4],
+ Reclaims: us[5],
+ AttributeChange: us[6],
+ }, nil
+}
+
+// LogOperationStats builds a LogOperationStats from a slice of uint32s.
+func logOperationStats(us []uint32) (LogOperationStats, error) {
+ if l := len(us); l != 5 {
+ return LogOperationStats{}, fmt.Errorf("incorrect number of values for XFS log operation stats: %d", l)
+ }
+
+ return LogOperationStats{
+ Writes: us[0],
+ Blocks: us[1],
+ NoInternalBuffers: us[2],
+ Force: us[3],
+ ForceSleep: us[4],
+ }, nil
+}
+
+// ReadWriteStats builds a ReadWriteStats from a slice of uint32s.
+func readWriteStats(us []uint32) (ReadWriteStats, error) {
+ if l := len(us); l != 2 {
+ return ReadWriteStats{}, fmt.Errorf("incorrect number of values for XFS read write stats: %d", l)
+ }
+
+ return ReadWriteStats{
+ Read: us[0],
+ Write: us[1],
+ }, nil
+}
+
+// AttributeOperationStats builds an AttributeOperationStats from a slice of uint32s.
+func attributeOperationStats(us []uint32) (AttributeOperationStats, error) {
+ if l := len(us); l != 4 {
+ return AttributeOperationStats{}, fmt.Errorf("incorrect number of values for XFS attribute operation stats: %d", l)
+ }
+
+ return AttributeOperationStats{
+ Get: us[0],
+ Set: us[1],
+ Remove: us[2],
+ List: us[3],
+ }, nil
+}
+
+// InodeClusteringStats builds an InodeClusteringStats from a slice of uint32s.
+func inodeClusteringStats(us []uint32) (InodeClusteringStats, error) {
+ if l := len(us); l != 3 {
+ return InodeClusteringStats{}, fmt.Errorf("incorrect number of values for XFS inode clustering stats: %d", l)
+ }
+
+ return InodeClusteringStats{
+ Iflush: us[0],
+ Flush: us[1],
+ FlushInode: us[2],
+ }, nil
+}
+
+// VnodeStats builds a VnodeStats from a slice of uint32s.
+func vnodeStats(us []uint32) (VnodeStats, error) {
+ // The attribute "Free" appears to not be available on older XFS
+ // stats versions. Therefore, 7 or 8 elements may appear in
+ // this slice.
+ l := len(us)
+ log.Println(l)
+ if l != 7 && l != 8 {
+ return VnodeStats{}, fmt.Errorf("incorrect number of values for XFS vnode stats: %d", l)
+ }
+
+ s := VnodeStats{
+ Active: us[0],
+ Allocate: us[1],
+ Get: us[2],
+ Hold: us[3],
+ Release: us[4],
+ Reclaim: us[5],
+ Remove: us[6],
+ }
+
+ // Skip adding free, unless it is present. The zero value will
+ // be used in place of an actual count.
+ if l == 7 {
+ return s, nil
+ }
+
+ s.Free = us[7]
+ return s, nil
+}
+
+// BufferStats builds a BufferStats from a slice of uint32s.
+func bufferStats(us []uint32) (BufferStats, error) {
+ if l := len(us); l != 9 {
+ return BufferStats{}, fmt.Errorf("incorrect number of values for XFS buffer stats: %d", l)
+ }
+
+ return BufferStats{
+ Get: us[0],
+ Create: us[1],
+ GetLocked: us[2],
+ GetLockedWaited: us[3],
+ BusyLocked: us[4],
+ MissLocked: us[5],
+ PageRetries: us[6],
+ PageFound: us[7],
+ GetRead: us[8],
+ }, nil
+}
+
+// ExtendedPrecisionStats builds an ExtendedPrecisionStats from a slice of uint32s.
+func extendedPrecisionStats(us []uint64) (ExtendedPrecisionStats, error) {
+ if l := len(us); l != 3 {
+ return ExtendedPrecisionStats{}, fmt.Errorf("incorrect number of values for XFS extended precision stats: %d", l)
+ }
+
+ return ExtendedPrecisionStats{
+ FlushBytes: us[0],
+ WriteBytes: us[1],
+ ReadBytes: us[2],
+ }, nil
+}
+
+// parseUint32s parses a slice of strings into a slice of uint32s.
+func parseUint32s(ss []string) ([]uint32, error) {
+ us := make([]uint32, 0, len(ss))
+ for _, s := range ss {
+ u, err := strconv.ParseUint(s, 10, 32)
+ if err != nil {
+ return nil, err
+ }
+
+ us = append(us, uint32(u))
+ }
+
+ return us, nil
+}
+
+// parseUint64s parses a slice of strings into a slice of uint64s.
+func parseUint64s(ss []string) ([]uint64, error) {
+ us := make([]uint64, 0, len(ss))
+ for _, s := range ss {
+ u, err := strconv.ParseUint(s, 10, 64)
+ if err != nil {
+ return nil, err
+ }
+
+ us = append(us, u)
+ }
+
+ return us, nil
+}
diff --git a/vendor/github.com/prometheus/procfs/xfs/parse_test.go b/vendor/github.com/prometheus/procfs/xfs/parse_test.go
new file mode 100644
index 0000000000..11ddb7425b
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/xfs/parse_test.go
@@ -0,0 +1,446 @@
+// Copyright 2017 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package xfs_test
+
+import (
+ "log"
+ "reflect"
+ "strings"
+ "testing"
+
+ "github.com/prometheus/procfs"
+ "github.com/prometheus/procfs/xfs"
+)
+
+func TestParseStats(t *testing.T) {
+ tests := []struct {
+ name string
+ s string
+ fs bool
+ stats *xfs.Stats
+ invalid bool
+ }{
+ {
+ name: "empty file OK",
+ },
+ {
+ name: "short or empty lines and unknown labels ignored",
+ s: "one\n\ntwo 1 2 3\n",
+ stats: &xfs.Stats{},
+ },
+ {
+ name: "bad uint32",
+ s: "extent_alloc XXX",
+ invalid: true,
+ },
+ {
+ name: "bad uint64",
+ s: "xpc XXX",
+ invalid: true,
+ },
+ {
+ name: "extent_alloc bad",
+ s: "extent_alloc 1",
+ invalid: true,
+ },
+ {
+ name: "extent_alloc OK",
+ s: "extent_alloc 1 2 3 4",
+ stats: &xfs.Stats{
+ ExtentAllocation: xfs.ExtentAllocationStats{
+ ExtentsAllocated: 1,
+ BlocksAllocated: 2,
+ ExtentsFreed: 3,
+ BlocksFreed: 4,
+ },
+ },
+ },
+ {
+ name: "abt bad",
+ s: "abt 1",
+ invalid: true,
+ },
+ {
+ name: "abt OK",
+ s: "abt 1 2 3 4",
+ stats: &xfs.Stats{
+ AllocationBTree: xfs.BTreeStats{
+ Lookups: 1,
+ Compares: 2,
+ RecordsInserted: 3,
+ RecordsDeleted: 4,
+ },
+ },
+ },
+ {
+ name: "blk_map bad",
+ s: "blk_map 1",
+ invalid: true,
+ },
+ {
+ name: "blk_map OK",
+ s: "blk_map 1 2 3 4 5 6 7",
+ stats: &xfs.Stats{
+ BlockMapping: xfs.BlockMappingStats{
+ Reads: 1,
+ Writes: 2,
+ Unmaps: 3,
+ ExtentListInsertions: 4,
+ ExtentListDeletions: 5,
+ ExtentListLookups: 6,
+ ExtentListCompares: 7,
+ },
+ },
+ },
+ {
+ name: "bmbt bad",
+ s: "bmbt 1",
+ invalid: true,
+ },
+ {
+ name: "bmbt OK",
+ s: "bmbt 1 2 3 4",
+ stats: &xfs.Stats{
+ BlockMapBTree: xfs.BTreeStats{
+ Lookups: 1,
+ Compares: 2,
+ RecordsInserted: 3,
+ RecordsDeleted: 4,
+ },
+ },
+ },
+ {
+ name: "dir bad",
+ s: "dir 1",
+ invalid: true,
+ },
+ {
+ name: "dir OK",
+ s: "dir 1 2 3 4",
+ stats: &xfs.Stats{
+ DirectoryOperation: xfs.DirectoryOperationStats{
+ Lookups: 1,
+ Creates: 2,
+ Removes: 3,
+ Getdents: 4,
+ },
+ },
+ },
+ {
+ name: "trans bad",
+ s: "trans 1",
+ invalid: true,
+ },
+ {
+ name: "trans OK",
+ s: "trans 1 2 3",
+ stats: &xfs.Stats{
+ Transaction: xfs.TransactionStats{
+ Sync: 1,
+ Async: 2,
+ Empty: 3,
+ },
+ },
+ },
+ {
+ name: "ig bad",
+ s: "ig 1",
+ invalid: true,
+ },
+ {
+ name: "ig OK",
+ s: "ig 1 2 3 4 5 6 7",
+ stats: &xfs.Stats{
+ InodeOperation: xfs.InodeOperationStats{
+ Attempts: 1,
+ Found: 2,
+ Recycle: 3,
+ Missed: 4,
+ Duplicate: 5,
+ Reclaims: 6,
+ AttributeChange: 7,
+ },
+ },
+ },
+ {
+ name: "log bad",
+ s: "log 1",
+ invalid: true,
+ },
+ {
+ name: "log OK",
+ s: "log 1 2 3 4 5",
+ stats: &xfs.Stats{
+ LogOperation: xfs.LogOperationStats{
+ Writes: 1,
+ Blocks: 2,
+ NoInternalBuffers: 3,
+ Force: 4,
+ ForceSleep: 5,
+ },
+ },
+ },
+ {
+ name: "rw bad",
+ s: "rw 1",
+ invalid: true,
+ },
+ {
+ name: "rw OK",
+ s: "rw 1 2",
+ stats: &xfs.Stats{
+ ReadWrite: xfs.ReadWriteStats{
+ Read: 1,
+ Write: 2,
+ },
+ },
+ },
+ {
+ name: "attr bad",
+ s: "attr 1",
+ invalid: true,
+ },
+ {
+ name: "attr OK",
+ s: "attr 1 2 3 4",
+ stats: &xfs.Stats{
+ AttributeOperation: xfs.AttributeOperationStats{
+ Get: 1,
+ Set: 2,
+ Remove: 3,
+ List: 4,
+ },
+ },
+ },
+ {
+ name: "icluster bad",
+ s: "icluster 1",
+ invalid: true,
+ },
+ {
+ name: "icluster OK",
+ s: "icluster 1 2 3",
+ stats: &xfs.Stats{
+ InodeClustering: xfs.InodeClusteringStats{
+ Iflush: 1,
+ Flush: 2,
+ FlushInode: 3,
+ },
+ },
+ },
+ {
+ name: "vnodes bad",
+ s: "vnodes 1",
+ invalid: true,
+ },
+ {
+ name: "vnodes (missing free) OK",
+ s: "vnodes 1 2 3 4 5 6 7",
+ stats: &xfs.Stats{
+ Vnode: xfs.VnodeStats{
+ Active: 1,
+ Allocate: 2,
+ Get: 3,
+ Hold: 4,
+ Release: 5,
+ Reclaim: 6,
+ Remove: 7,
+ },
+ },
+ },
+ {
+ name: "vnodes (with free) OK",
+ s: "vnodes 1 2 3 4 5 6 7 8",
+ stats: &xfs.Stats{
+ Vnode: xfs.VnodeStats{
+ Active: 1,
+ Allocate: 2,
+ Get: 3,
+ Hold: 4,
+ Release: 5,
+ Reclaim: 6,
+ Remove: 7,
+ Free: 8,
+ },
+ },
+ },
+ {
+ name: "buf bad",
+ s: "buf 1",
+ invalid: true,
+ },
+ {
+ name: "buf OK",
+ s: "buf 1 2 3 4 5 6 7 8 9",
+ stats: &xfs.Stats{
+ Buffer: xfs.BufferStats{
+ Get: 1,
+ Create: 2,
+ GetLocked: 3,
+ GetLockedWaited: 4,
+ BusyLocked: 5,
+ MissLocked: 6,
+ PageRetries: 7,
+ PageFound: 8,
+ GetRead: 9,
+ },
+ },
+ },
+ {
+ name: "xpc bad",
+ s: "xpc 1",
+ invalid: true,
+ },
+ {
+ name: "xpc OK",
+ s: "xpc 1 2 3",
+ stats: &xfs.Stats{
+ ExtendedPrecision: xfs.ExtendedPrecisionStats{
+ FlushBytes: 1,
+ WriteBytes: 2,
+ ReadBytes: 3,
+ },
+ },
+ },
+ {
+ name: "fixtures OK",
+ fs: true,
+ stats: &xfs.Stats{
+ ExtentAllocation: xfs.ExtentAllocationStats{
+ ExtentsAllocated: 92447,
+ BlocksAllocated: 97589,
+ ExtentsFreed: 92448,
+ BlocksFreed: 93751,
+ },
+ AllocationBTree: xfs.BTreeStats{
+ Lookups: 0,
+ Compares: 0,
+ RecordsInserted: 0,
+ RecordsDeleted: 0,
+ },
+ BlockMapping: xfs.BlockMappingStats{
+ Reads: 1767055,
+ Writes: 188820,
+ Unmaps: 184891,
+ ExtentListInsertions: 92447,
+ ExtentListDeletions: 92448,
+ ExtentListLookups: 2140766,
+ ExtentListCompares: 0,
+ },
+ BlockMapBTree: xfs.BTreeStats{
+ Lookups: 0,
+ Compares: 0,
+ RecordsInserted: 0,
+ RecordsDeleted: 0,
+ },
+ DirectoryOperation: xfs.DirectoryOperationStats{
+ Lookups: 185039,
+ Creates: 92447,
+ Removes: 92444,
+ Getdents: 136422,
+ },
+ Transaction: xfs.TransactionStats{
+ Sync: 706,
+ Async: 944304,
+ Empty: 0,
+ },
+ InodeOperation: xfs.InodeOperationStats{
+ Attempts: 185045,
+ Found: 58807,
+ Recycle: 0,
+ Missed: 126238,
+ Duplicate: 0,
+ Reclaims: 33637,
+ AttributeChange: 22,
+ },
+ LogOperation: xfs.LogOperationStats{
+ Writes: 2883,
+ Blocks: 113448,
+ NoInternalBuffers: 9,
+ Force: 17360,
+ ForceSleep: 739,
+ },
+ ReadWrite: xfs.ReadWriteStats{
+ Read: 107739,
+ Write: 94045,
+ },
+ AttributeOperation: xfs.AttributeOperationStats{
+ Get: 4,
+ Set: 0,
+ Remove: 0,
+ List: 0,
+ },
+ InodeClustering: xfs.InodeClusteringStats{
+ Iflush: 8677,
+ Flush: 7849,
+ FlushInode: 135802,
+ },
+ Vnode: xfs.VnodeStats{
+ Active: 92601,
+ Allocate: 0,
+ Get: 0,
+ Hold: 0,
+ Release: 92444,
+ Reclaim: 92444,
+ Remove: 92444,
+ Free: 0,
+ },
+ Buffer: xfs.BufferStats{
+ Get: 2666287,
+ Create: 7122,
+ GetLocked: 2659202,
+ GetLockedWaited: 3599,
+ BusyLocked: 2,
+ MissLocked: 7085,
+ PageRetries: 0,
+ PageFound: 10297,
+ GetRead: 7085,
+ },
+ ExtendedPrecision: xfs.ExtendedPrecisionStats{
+ FlushBytes: 399724544,
+ WriteBytes: 92823103,
+ ReadBytes: 86219234,
+ },
+ },
+ },
+ }
+
+ for i, tt := range tests {
+ t.Logf("[%02d] test %q", i, tt.name)
+
+ var (
+ stats *xfs.Stats
+ err error
+ )
+
+ if tt.s != "" {
+ stats, err = xfs.ParseStats(strings.NewReader(tt.s))
+ }
+ if tt.fs {
+ stats, err = procfs.FS("../fixtures").XFSStats()
+ }
+
+ if tt.invalid && err == nil {
+ t.Error("expected an error, but none occurred")
+ }
+ if !tt.invalid && err != nil {
+ t.Errorf("unexpected error: %v", err)
+ }
+
+ if want, have := tt.stats, stats; !reflect.DeepEqual(want, have) {
+ log.Printf("stats: %#v", have)
+ t.Errorf("unexpected XFS stats:\nwant:\n%v\nhave:\n%v", want, have)
+ }
+ }
+}
diff --git a/vendor/github.com/prometheus/procfs/xfs/xfs.go b/vendor/github.com/prometheus/procfs/xfs/xfs.go
new file mode 100644
index 0000000000..ed77d907ae
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/xfs/xfs.go
@@ -0,0 +1,158 @@
+// Copyright 2017 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package xfs provides access to statistics exposed by the XFS filesystem.
+package xfs
+
+// Stats contains XFS filesystem runtime statistics, parsed from
+// /proc/fs/xfs/stat.
+//
+// The names and meanings of each statistic were taken from
+// http://xfs.org/index.php/Runtime_Stats and xfs_stats.h in the Linux
+// kernel source. Most counters are uint32s (same data types used in
+// xfs_stats.h), but some of the "extended precision stats" are uint64s.
+type Stats struct {
+ ExtentAllocation ExtentAllocationStats
+ AllocationBTree BTreeStats
+ BlockMapping BlockMappingStats
+ BlockMapBTree BTreeStats
+ DirectoryOperation DirectoryOperationStats
+ Transaction TransactionStats
+ InodeOperation InodeOperationStats
+ LogOperation LogOperationStats
+ ReadWrite ReadWriteStats
+ AttributeOperation AttributeOperationStats
+ InodeClustering InodeClusteringStats
+ Vnode VnodeStats
+ Buffer BufferStats
+ ExtendedPrecision ExtendedPrecisionStats
+}
+
+// ExtentAllocationStats contains statistics regarding XFS extent allocations.
+type ExtentAllocationStats struct {
+ ExtentsAllocated uint32
+ BlocksAllocated uint32
+ ExtentsFreed uint32
+ BlocksFreed uint32
+}
+
+// BTreeStats contains statistics regarding an XFS internal B-tree.
+type BTreeStats struct {
+ Lookups uint32
+ Compares uint32
+ RecordsInserted uint32
+ RecordsDeleted uint32
+}
+
+// BlockMappingStats contains statistics regarding XFS block maps.
+type BlockMappingStats struct {
+ Reads uint32
+ Writes uint32
+ Unmaps uint32
+ ExtentListInsertions uint32
+ ExtentListDeletions uint32
+ ExtentListLookups uint32
+ ExtentListCompares uint32
+}
+
+// DirectoryOperationStats contains statistics regarding XFS directory entries.
+type DirectoryOperationStats struct {
+ Lookups uint32
+ Creates uint32
+ Removes uint32
+ Getdents uint32
+}
+
+// TransactionStats contains statistics regarding XFS metadata transactions.
+type TransactionStats struct {
+ Sync uint32
+ Async uint32
+ Empty uint32
+}
+
+// InodeOperationStats contains statistics regarding XFS inode operations.
+type InodeOperationStats struct {
+ Attempts uint32
+ Found uint32
+ Recycle uint32
+ Missed uint32
+ Duplicate uint32
+ Reclaims uint32
+ AttributeChange uint32
+}
+
+// LogOperationStats contains statistics regarding the XFS log buffer.
+type LogOperationStats struct {
+ Writes uint32
+ Blocks uint32
+ NoInternalBuffers uint32
+ Force uint32
+ ForceSleep uint32
+}
+
+// ReadWriteStats contains statistics regarding the number of read and write
+// system calls for XFS filesystems.
+type ReadWriteStats struct {
+ Read uint32
+ Write uint32
+}
+
+// AttributeOperationStats contains statistics regarding manipulation of
+// XFS extended file attributes.
+type AttributeOperationStats struct {
+ Get uint32
+ Set uint32
+ Remove uint32
+ List uint32
+}
+
+// InodeClusteringStats contains statistics regarding XFS inode clustering
+// operations.
+type InodeClusteringStats struct {
+ Iflush uint32
+ Flush uint32
+ FlushInode uint32
+}
+
+// VnodeStats contains statistics regarding XFS vnode operations.
+type VnodeStats struct {
+ Active uint32
+ Allocate uint32
+ Get uint32
+ Hold uint32
+ Release uint32
+ Reclaim uint32
+ Remove uint32
+ Free uint32
+}
+
+// BufferStats contains statistics regarding XFS read/write I/O buffers.
+type BufferStats struct {
+ Get uint32
+ Create uint32
+ GetLocked uint32
+ GetLockedWaited uint32
+ BusyLocked uint32
+ MissLocked uint32
+ PageRetries uint32
+ PageFound uint32
+ GetRead uint32
+}
+
+// ExtendedPrecisionStats contains high precision counters used to track the
+// total number of bytes read, written, or flushed, during XFS operations.
+type ExtendedPrecisionStats struct {
+ FlushBytes uint64
+ WriteBytes uint64
+ ReadBytes uint64
+}
diff --git a/vendor/github.com/spf13/cobra/.travis.yml b/vendor/github.com/spf13/cobra/.travis.yml
index bd72adf685..42d1f57d30 100644
--- a/vendor/github.com/spf13/cobra/.travis.yml
+++ b/vendor/github.com/spf13/cobra/.travis.yml
@@ -5,8 +5,9 @@ matrix:
- go: 1.4.3
env: NOVET=true # No bundled vet.
- go: 1.5.4
- - go: 1.6.3
- - go: 1.7
+ - go: 1.6.4
+ - go: 1.7.5
+ - go: 1.8
- go: tip
allow_failures:
- go: tip
diff --git a/vendor/github.com/spf13/cobra/README.md b/vendor/github.com/spf13/cobra/README.md
index 2efda59205..2de9840122 100644
--- a/vendor/github.com/spf13/cobra/README.md
+++ b/vendor/github.com/spf13/cobra/README.md
@@ -8,6 +8,7 @@ Many of the most widely used Go projects are built using Cobra including:
* [Hugo](http://gohugo.io)
* [rkt](https://github.com/coreos/rkt)
* [etcd](https://github.com/coreos/etcd)
+* [Docker](https://github.com/docker/docker)
* [Docker (distribution)](https://github.com/docker/distribution)
* [OpenShift](https://www.openshift.com/)
* [Delve](https://github.com/derekparker/delve)
@@ -755,7 +756,7 @@ providing a way to handle the errors in one location. The current list of functi
* PersistentPostRunE
If you would like to silence the default `error` and `usage` output in favor of your own, you can set `SilenceUsage`
-and `SilenceErrors` to `false` on the command. A child command respects these flags if they are set on the parent
+and `SilenceErrors` to `true` on the command. A child command respects these flags if they are set on the parent
command.
**Example Usage using RunE:**
diff --git a/vendor/github.com/spf13/cobra/command.go b/vendor/github.com/spf13/cobra/command.go
index 3ee1a0a9d1..ae3930dfc6 100644
--- a/vendor/github.com/spf13/cobra/command.go
+++ b/vendor/github.com/spf13/cobra/command.go
@@ -57,6 +57,9 @@ type Command struct {
Deprecated string
// Is this command hidden and should NOT show up in the list of available commands?
Hidden bool
+ // Annotations are key/value pairs that can be used by applications to identify or
+ // group commands
+ Annotations map[string]string
// Full set of flags
flags *flag.FlagSet
// Set of flags childrens of this command will inherit
@@ -152,12 +155,12 @@ func (c *Command) SetUsageTemplate(s string) {
}
// SetFlagErrorFunc sets a function to generate an error when flag parsing
-// fails
+// fails.
func (c *Command) SetFlagErrorFunc(f func(*Command, error) error) {
c.flagErrorFunc = f
}
-// SetHelpFunc sets help function. Can be defined by Application
+// SetHelpFunc sets help function. Can be defined by Application.
func (c *Command) SetHelpFunc(f func(*Command, []string)) {
c.helpFunc = f
}
@@ -184,7 +187,7 @@ func (c *Command) SetGlobalNormalizationFunc(n func(f *flag.FlagSet, name string
}
}
-// OutOrStdout returns output to stdout
+// OutOrStdout returns output to stdout.
func (c *Command) OutOrStdout() io.Writer {
return c.getOut(os.Stdout)
}
@@ -342,19 +345,19 @@ Aliases:
{{end}}{{if .HasExample}}
Examples:
-{{ .Example }}{{end}}{{ if .HasAvailableSubCommands}}
+{{ .Example }}{{end}}{{if .HasAvailableSubCommands}}
-Available Commands:{{range .Commands}}{{if .IsAvailableCommand}}
- {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasAvailableLocalFlags}}
+Available Commands:{{range .Commands}}{{if (or .IsAvailableCommand (eq .Name "help"))}}
+ {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}}
Flags:
-{{.LocalFlags.FlagUsages | trimRightSpace}}{{end}}{{ if .HasAvailableInheritedFlags}}
+{{.LocalFlags.FlagUsages | trimRightSpace}}{{end}}{{if .HasAvailableInheritedFlags}}
Global Flags:
{{.InheritedFlags.FlagUsages | trimRightSpace}}{{end}}{{if .HasHelpSubCommands}}
-Additional help topics:{{range .Commands}}{{if .IsHelpCommand}}
- {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasAvailableSubCommands }}
+Additional help topics:{{range .Commands}}{{if .IsAdditionalHelpTopicCommand}}
+ {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableSubCommands}}
Use "{{.CommandPath}} [command] --help" for more information about a command.{{end}}
`
@@ -381,20 +384,18 @@ func (c *Command) resetChildrensParents() {
}
}
-// Test if the named flag is a boolean flag.
-func isBooleanFlag(name string, f *flag.FlagSet) bool {
+func hasNoOptDefVal(name string, f *flag.FlagSet) bool {
flag := f.Lookup(name)
if flag == nil {
return false
}
- return flag.Value.Type() == "bool"
+ return len(flag.NoOptDefVal) > 0
}
-// Test if the named flag is a boolean flag.
-func isBooleanShortFlag(name string, f *flag.FlagSet) bool {
+func shortHasNoOptDefVal(name string, fs *flag.FlagSet) bool {
result := false
- f.VisitAll(func(f *flag.Flag) {
- if f.Shorthand == name && f.Value.Type() == "bool" {
+ fs.VisitAll(func(flag *flag.Flag) {
+ if flag.Shorthand == name && len(flag.NoOptDefVal) > 0 {
result = true
}
})
@@ -420,8 +421,8 @@ func stripFlags(args []string, c *Command) []string {
inQuote = true
case strings.HasPrefix(y, "--") && !strings.Contains(y, "="):
// TODO: this isn't quite right, we should really check ahead for 'true' or 'false'
- inFlag = !isBooleanFlag(y[2:], c.Flags())
- case strings.HasPrefix(y, "-") && !strings.Contains(y, "=") && len(y) == 2 && !isBooleanShortFlag(y[1:], c.Flags()):
+ inFlag = !hasNoOptDefVal(y[2:], c.Flags())
+ case strings.HasPrefix(y, "-") && !strings.Contains(y, "=") && len(y) == 2 && !shortHasNoOptDefVal(y[1:], c.Flags()):
inFlag = true
case inFlag:
inFlag = false
@@ -455,7 +456,7 @@ func argsMinusFirstX(args []string, x string) []string {
return args
}
-// Find finds the target command given the args and command tree
+// Find the target command given the args and command tree
// Meant to be run on the highest node. Only searches down.
func (c *Command) Find(args []string) (*Command, []string, error) {
if c == nil {
@@ -695,7 +696,6 @@ func (c *Command) Execute() error {
// ExecuteC executes the command.
func (c *Command) ExecuteC() (cmd *Command, err error) {
-
// Regardless of what command execute is called on, run on Root only
if c.HasParent() {
return c.Root().ExecuteC()
@@ -780,7 +780,7 @@ func (c *Command) initHelpCmd() {
Run: func(c *Command, args []string) {
cmd, _, e := c.Root().Find(args)
if cmd == nil || e != nil {
- c.Printf("Unknown help topic %#q.", args)
+ c.Printf("Unknown help topic %#q\n", args)
c.Root().Usage()
} else {
cmd.Help()
@@ -969,7 +969,8 @@ func (c *Command) Name() string {
if i >= 0 {
name = name[:i]
}
- return name
+ c.name = name
+ return c.name
}
// HasAlias determines if a given string is an alias of the command.
@@ -1020,11 +1021,12 @@ func (c *Command) IsAvailableCommand() bool {
return false
}
-// IsHelpCommand determines if a command is a 'help' command; a help command is
-// determined by the fact that it is NOT runnable/hidden/deprecated, and has no
-// sub commands that are runnable/hidden/deprecated.
-func (c *Command) IsHelpCommand() bool {
-
+// IsAdditionalHelpTopicCommand determines if a command is an additional
+// help topic command; additional help topic command is determined by the
+// fact that it is NOT runnable/hidden/deprecated, and has no sub commands that
+// are runnable/hidden/deprecated.
+// Concrete example: https://github.com/spf13/cobra/issues/393#issuecomment-282741924.
+func (c *Command) IsAdditionalHelpTopicCommand() bool {
// if a command is runnable, deprecated, or hidden it is not a 'help' command
if c.Runnable() || len(c.Deprecated) != 0 || c.Hidden {
return false
@@ -1032,7 +1034,7 @@ func (c *Command) IsHelpCommand() bool {
// if any non-help sub commands are found, the command is not a 'help' command
for _, sub := range c.commands {
- if !sub.IsHelpCommand() {
+ if !sub.IsAdditionalHelpTopicCommand() {
return false
}
}
@@ -1045,10 +1047,9 @@ func (c *Command) IsHelpCommand() bool {
// that need to be shown in the usage/help default template under 'additional help
// topics'.
func (c *Command) HasHelpSubCommands() bool {
-
// return true on the first found available 'help' sub command
for _, sub := range c.commands {
- if sub.IsHelpCommand() {
+ if sub.IsAdditionalHelpTopicCommand() {
return true
}
}
@@ -1060,7 +1061,6 @@ func (c *Command) HasHelpSubCommands() bool {
// HasAvailableSubCommands determines if a command has available sub commands that
// need to be shown in the usage/help default template under 'available commands'.
func (c *Command) HasAvailableSubCommands() bool {
-
// return true on the first found available (non deprecated/help/hidden)
// sub command
for _, sub := range c.commands {
diff --git a/vendor/github.com/spf13/cobra/doc/man_docs.go b/vendor/github.com/spf13/cobra/doc/man_docs.go
index fd7107c424..b9266c367c 100644
--- a/vendor/github.com/spf13/cobra/doc/man_docs.go
+++ b/vendor/github.com/spf13/cobra/doc/man_docs.go
@@ -49,7 +49,7 @@ func GenManTreeFromOpts(cmd *cobra.Command, opts GenManTreeOptions) error {
header = &GenManHeader{}
}
for _, c := range cmd.Commands() {
- if !c.IsAvailableCommand() || c.IsHelpCommand() {
+ if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() {
continue
}
if err := GenManTreeFromOpts(c, opts); err != nil {
@@ -216,7 +216,7 @@ func genMan(cmd *cobra.Command, header *GenManHeader) []byte {
children := cmd.Commands()
sort.Sort(byName(children))
for _, c := range children {
- if !c.IsAvailableCommand() || c.IsHelpCommand() {
+ if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() {
continue
}
seealso := fmt.Sprintf("**%s-%s(%s)**", dashCommandName, c.Name(), header.Section)
diff --git a/vendor/github.com/spf13/cobra/doc/md_docs.go b/vendor/github.com/spf13/cobra/doc/md_docs.go
index fa13631804..8d159c1d73 100644
--- a/vendor/github.com/spf13/cobra/doc/md_docs.go
+++ b/vendor/github.com/spf13/cobra/doc/md_docs.go
@@ -119,7 +119,7 @@ func GenMarkdownCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string)
sort.Sort(byName(children))
for _, child := range children {
- if !child.IsAvailableCommand() || child.IsHelpCommand() {
+ if !child.IsAvailableCommand() || child.IsAdditionalHelpTopicCommand() {
continue
}
cname := name + " " + child.Name()
@@ -149,7 +149,7 @@ func GenMarkdownTree(cmd *cobra.Command, dir string) error {
func GenMarkdownTreeCustom(cmd *cobra.Command, dir string, filePrepender, linkHandler func(string) string) error {
for _, c := range cmd.Commands() {
- if !c.IsAvailableCommand() || c.IsHelpCommand() {
+ if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() {
continue
}
if err := GenMarkdownTreeCustom(c, dir, filePrepender, linkHandler); err != nil {
diff --git a/vendor/github.com/spf13/cobra/doc/util.go b/vendor/github.com/spf13/cobra/doc/util.go
index a7d2765a90..8d3dbecec8 100644
--- a/vendor/github.com/spf13/cobra/doc/util.go
+++ b/vendor/github.com/spf13/cobra/doc/util.go
@@ -27,7 +27,7 @@ func hasSeeAlso(cmd *cobra.Command) bool {
return true
}
for _, c := range cmd.Commands() {
- if !c.IsAvailableCommand() || c.IsHelpCommand() {
+ if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() {
continue
}
return true
diff --git a/vendor/github.com/spf13/cobra/doc/yaml_docs.go b/vendor/github.com/spf13/cobra/doc/yaml_docs.go
index 75474d299d..ac8db89ebe 100644
--- a/vendor/github.com/spf13/cobra/doc/yaml_docs.go
+++ b/vendor/github.com/spf13/cobra/doc/yaml_docs.go
@@ -57,7 +57,7 @@ func GenYamlTree(cmd *cobra.Command, dir string) error {
// GenYamlTreeCustom creates yaml structured ref files
func GenYamlTreeCustom(cmd *cobra.Command, dir string, filePrepender, linkHandler func(string) string) error {
for _, c := range cmd.Commands() {
- if !c.IsAvailableCommand() || c.IsHelpCommand() {
+ if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() {
continue
}
if err := GenYamlTreeCustom(c, dir, filePrepender, linkHandler); err != nil {
@@ -117,7 +117,7 @@ func GenYamlCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string) str
children := cmd.Commands()
sort.Sort(byName(children))
for _, child := range children {
- if !child.IsAvailableCommand() || child.IsHelpCommand() {
+ if !child.IsAvailableCommand() || child.IsAdditionalHelpTopicCommand() {
continue
}
result = append(result, child.Name()+" - "+child.Short)
diff --git a/vendor/github.com/tylerb/graceful/README.md b/vendor/github.com/tylerb/graceful/README.md
index 328c3acf89..c641b6e784 100644
--- a/vendor/github.com/tylerb/graceful/README.md
+++ b/vendor/github.com/tylerb/graceful/README.md
@@ -3,6 +3,11 @@ graceful [](htt
Graceful is a Go 1.3+ package enabling graceful shutdown of http.Handler servers.
+## Using Go 1.8?
+
+If you are using Go 1.8, you may not need to use this library! Consider using `http.Server`'s built-in [Shutdown()](https://golang.org/pkg/net/http/#Server.Shutdown)
+method for graceful shutdowns.
+
## Installation
To install, simply execute:
diff --git a/vendor/github.com/tylerb/graceful/graceful.go b/vendor/github.com/tylerb/graceful/graceful.go
index d6a9ca068a..ebf0aeb7dc 100644
--- a/vendor/github.com/tylerb/graceful/graceful.go
+++ b/vendor/github.com/tylerb/graceful/graceful.go
@@ -366,6 +366,7 @@ func (srv *Server) manageConnections(add, idle, active, remove chan net.Conn, sh
select {
case conn := <-add:
srv.connections[conn] = struct{}{}
+ srv.idleConnections[conn] = struct{}{} // Newly-added connections are considered idle until they become active.
case conn := <-idle:
srv.idleConnections[conn] = struct{}{}
case conn := <-active:
diff --git a/vendor/github.com/xenolf/lego/README.md b/vendor/github.com/xenolf/lego/README.md
index 9be562944e..852f0a8338 100644
--- a/vendor/github.com/xenolf/lego/README.md
+++ b/vendor/github.com/xenolf/lego/README.md
@@ -23,7 +23,11 @@ To build lego inside a Docker container, just run
```
docker build -t lego .
```
-
+##### From the package manager
+- [ArchLinux (AUR)](https://aur.archlinux.org/packages/lego-git):
+```
+yaourt -S lego-git
+```
#### Features
- Register with CA
diff --git a/vendor/github.com/xenolf/lego/acme/client.go b/vendor/github.com/xenolf/lego/acme/client.go
index e824f5080f..ba56e796ca 100644
--- a/vendor/github.com/xenolf/lego/acme/client.go
+++ b/vendor/github.com/xenolf/lego/acme/client.go
@@ -535,6 +535,7 @@ func (c *Client) getChallenges(domains []string) ([]authorizationResource, map[s
links := parseLinks(hdr["Link"])
if links["next"] == "" {
logf("[ERROR][%s] acme: Server did not provide next link to proceed", domain)
+ errc <- domainError{Domain: domain, Error: errors.New("Server did not provide next link to proceed")}
return
}
@@ -560,12 +561,20 @@ func (c *Client) getChallenges(domains []string) ([]authorizationResource, map[s
}
}
+ logAuthz(challenges)
+
close(resc)
close(errc)
return challenges, failures
}
+func logAuthz(authz []authorizationResource) {
+ for _, auth := range authz {
+ logf("[INFO][%s] AuthURL: %s", auth.Domain, auth.AuthURL)
+ }
+}
+
func (c *Client) requestCertificate(authz []authorizationResource, bundle bool, privKey crypto.PrivateKey, mustStaple bool) (CertificateResource, error) {
if len(authz) == 0 {
return CertificateResource{}, errors.New("Passed no authorizations to requestCertificate!")
diff --git a/vendor/github.com/xenolf/lego/acme/client_test.go b/vendor/github.com/xenolf/lego/acme/client_test.go
index e309554f30..b18334c8a8 100644
--- a/vendor/github.com/xenolf/lego/acme/client_test.go
+++ b/vendor/github.com/xenolf/lego/acme/client_test.go
@@ -10,6 +10,7 @@ import (
"net/http/httptest"
"strings"
"testing"
+ "time"
)
func TestNewClient(t *testing.T) {
@@ -118,6 +119,39 @@ func TestClientOptPort(t *testing.T) {
}
}
+func TestNotHoldingLockWhileMakingHTTPRequests(t *testing.T) {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ time.Sleep(250 * time.Millisecond)
+ w.Header().Add("Replay-Nonce", "12345")
+ w.Header().Add("Retry-After", "0")
+ writeJSONResponse(w, &challenge{Type: "http-01", Status: "Valid", URI: "http://example.com/", Token: "token"})
+ }))
+ defer ts.Close()
+
+ privKey, _ := rsa.GenerateKey(rand.Reader, 512)
+ j := &jws{privKey: privKey, directoryURL: ts.URL}
+ ch := make(chan bool)
+ resultCh := make(chan bool)
+ go func() {
+ j.Nonce()
+ ch <- true
+ }()
+ go func() {
+ j.Nonce()
+ ch <- true
+ }()
+ go func() {
+ <-ch
+ <-ch
+ resultCh <- true
+ }()
+ select {
+ case <-resultCh:
+ case <-time.After(400 * time.Millisecond):
+ t.Fatal("JWS is probably holding a lock while making HTTP request")
+ }
+}
+
func TestValidate(t *testing.T) {
var statuses []string
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@@ -168,6 +202,43 @@ func TestValidate(t *testing.T) {
}
}
+func TestGetChallenges(t *testing.T) {
+ var ts *httptest.Server
+ ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ switch r.Method {
+ case "GET", "HEAD":
+ w.Header().Add("Replay-Nonce", "12345")
+ w.Header().Add("Retry-After", "0")
+ writeJSONResponse(w, directory{NewAuthzURL: ts.URL, NewCertURL: ts.URL, NewRegURL: ts.URL, RevokeCertURL: ts.URL})
+ case "POST":
+ writeJSONResponse(w, authorization{})
+ }
+ }))
+ defer ts.Close()
+
+ keyBits := 512 // small value keeps test fast
+ keyType := RSA2048
+ key, err := rsa.GenerateKey(rand.Reader, keyBits)
+ if err != nil {
+ t.Fatal("Could not generate test key:", err)
+ }
+ user := mockUser{
+ email: "test@test.com",
+ regres: &RegistrationResource{NewAuthzURL: ts.URL},
+ privatekey: key,
+ }
+
+ client, err := NewClient(ts.URL, user, keyType)
+ if err != nil {
+ t.Fatalf("Could not create client: %v", err)
+ }
+
+ _, failures := client.getChallenges([]string{"example.com"})
+ if failures["example.com"] == nil {
+ t.Fatal("Expecting \"Server did not provide next link to proceed\" error, got nil")
+ }
+}
+
// writeJSONResponse marshals the body as JSON and writes it to the response.
func writeJSONResponse(w http.ResponseWriter, body interface{}) {
bs, err := json.Marshal(body)
diff --git a/vendor/github.com/xenolf/lego/acme/error.go b/vendor/github.com/xenolf/lego/acme/error.go
index 6d7013cf1d..e4bc934c25 100644
--- a/vendor/github.com/xenolf/lego/acme/error.go
+++ b/vendor/github.com/xenolf/lego/acme/error.go
@@ -8,7 +8,10 @@ import (
"strings"
)
-const tosAgreementError = "Must agree to subscriber agreement before any further actions"
+const (
+ tosAgreementError = "Must agree to subscriber agreement before any further actions"
+ invalidNonceError = "JWS has invalid anti-replay nonce"
+)
// RemoteError is the base type for all errors specific to the ACME protocol.
type RemoteError struct {
@@ -28,6 +31,12 @@ type TOSError struct {
RemoteError
}
+// NonceError represents the error which is returned if the
+// nonce sent by the client was not accepted by the server.
+type NonceError struct {
+ RemoteError
+}
+
type domainError struct {
Domain string
Error error
@@ -73,6 +82,10 @@ func handleHTTPError(resp *http.Response) error {
return TOSError{errorDetail}
}
+ if errorDetail.StatusCode == http.StatusBadRequest && strings.HasPrefix(errorDetail.Detail, invalidNonceError) {
+ return NonceError{errorDetail}
+ }
+
return errorDetail
}
diff --git a/vendor/github.com/xenolf/lego/acme/http.go b/vendor/github.com/xenolf/lego/acme/http.go
index 180db786d4..dc958046a5 100644
--- a/vendor/github.com/xenolf/lego/acme/http.go
+++ b/vendor/github.com/xenolf/lego/acme/http.go
@@ -31,14 +31,14 @@ const (
func httpHead(url string) (resp *http.Response, err error) {
req, err := http.NewRequest("HEAD", url, nil)
if err != nil {
- return nil, err
+ return nil, fmt.Errorf("failed to head %q: %v", url, err)
}
req.Header.Set("User-Agent", userAgent())
resp, err = HTTPClient.Do(req)
if err != nil {
- return resp, err
+ return resp, fmt.Errorf("failed to do head %q: %v", url, err)
}
resp.Body.Close()
return resp, err
@@ -49,7 +49,7 @@ func httpHead(url string) (resp *http.Response, err error) {
func httpPost(url string, bodyType string, body io.Reader) (resp *http.Response, err error) {
req, err := http.NewRequest("POST", url, body)
if err != nil {
- return nil, err
+ return nil, fmt.Errorf("failed to post %q: %v", url, err)
}
req.Header.Set("Content-Type", bodyType)
req.Header.Set("User-Agent", userAgent())
@@ -62,7 +62,7 @@ func httpPost(url string, bodyType string, body io.Reader) (resp *http.Response,
func httpGet(url string) (resp *http.Response, err error) {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
- return nil, err
+ return nil, fmt.Errorf("failed to get %q: %v", url, err)
}
req.Header.Set("User-Agent", userAgent())
@@ -74,7 +74,7 @@ func httpGet(url string) (resp *http.Response, err error) {
func getJSON(uri string, respBody interface{}) (http.Header, error) {
resp, err := httpGet(uri)
if err != nil {
- return nil, fmt.Errorf("failed to get %q: %v", uri, err)
+ return nil, fmt.Errorf("failed to get json %q: %v", uri, err)
}
defer resp.Body.Close()
diff --git a/vendor/github.com/xenolf/lego/acme/jws.go b/vendor/github.com/xenolf/lego/acme/jws.go
index 2a1fc244d9..1b4d29d533 100644
--- a/vendor/github.com/xenolf/lego/acme/jws.go
+++ b/vendor/github.com/xenolf/lego/acme/jws.go
@@ -16,8 +16,7 @@ import (
type jws struct {
directoryURL string
privKey crypto.PrivateKey
- nonces []string
- sync.Mutex
+ nonces nonceManager
}
func keyAsJWK(key interface{}) *jose.JsonWebKey {
@@ -38,19 +37,31 @@ func keyAsJWK(key interface{}) *jose.JsonWebKey {
func (j *jws) post(url string, content []byte) (*http.Response, error) {
signedContent, err := j.signContent(content)
if err != nil {
- return nil, err
+ return nil, fmt.Errorf("Failed to sign content -> %s", err.Error())
}
resp, err := httpPost(url, "application/jose+json", bytes.NewBuffer([]byte(signedContent.FullSerialize())))
- if err != nil {
- return nil, err
+
+ // Even in case of an error, the response should still contain a nonce.
+ nonce, nonceErr := getNonceFromResponse(resp)
+ if nonceErr == nil {
+ j.nonces.Push(nonce)
}
- j.Lock()
- defer j.Unlock()
- j.getNonceFromResponse(resp)
+ if err != nil {
+ switch err.(type) {
+ case NonceError:
+ // In case of a nonce error - retry once
+ resp, err = httpPost(url, "application/jose+json", bytes.NewBuffer([]byte(signedContent.FullSerialize())))
+ if err != nil {
+ return nil, fmt.Errorf("Failed to HTTP POST to %s -> %s", url, err.Error())
+ }
+ default:
+ return nil, fmt.Errorf("Failed to HTTP POST to %s -> %s", url, err.Error())
+ }
+ }
- return resp, err
+ return resp, nil
}
func (j *jws) signContent(content []byte) (*jose.JsonWebSignature, error) {
@@ -69,49 +80,63 @@ func (j *jws) signContent(content []byte) (*jose.JsonWebSignature, error) {
signer, err := jose.NewSigner(alg, j.privKey)
if err != nil {
- return nil, err
+ return nil, fmt.Errorf("Failed to create jose signer -> %s", err.Error())
}
signer.SetNonceSource(j)
signed, err := signer.Sign(content)
if err != nil {
- return nil, err
+ return nil, fmt.Errorf("Failed to sign content -> %s", err.Error())
}
return signed, nil
}
-func (j *jws) getNonceFromResponse(resp *http.Response) error {
+func (j *jws) Nonce() (string, error) {
+ if nonce, ok := j.nonces.Pop(); ok {
+ return nonce, nil
+ }
+
+ return getNonce(j.directoryURL)
+}
+
+type nonceManager struct {
+ nonces []string
+ sync.Mutex
+}
+
+func (n *nonceManager) Pop() (string, bool) {
+ n.Lock()
+ defer n.Unlock()
+
+ if len(n.nonces) == 0 {
+ return "", false
+ }
+
+ nonce := n.nonces[len(n.nonces)-1]
+ n.nonces = n.nonces[:len(n.nonces)-1]
+ return nonce, true
+}
+
+func (n *nonceManager) Push(nonce string) {
+ n.Lock()
+ defer n.Unlock()
+ n.nonces = append(n.nonces, nonce)
+}
+
+func getNonce(url string) (string, error) {
+ resp, err := httpHead(url)
+ if err != nil {
+ return "", fmt.Errorf("Failed to get nonce from HTTP HEAD -> %s", err.Error())
+ }
+
+ return getNonceFromResponse(resp)
+}
+
+func getNonceFromResponse(resp *http.Response) (string, error) {
nonce := resp.Header.Get("Replay-Nonce")
if nonce == "" {
- return fmt.Errorf("Server did not respond with a proper nonce header.")
+ return "", fmt.Errorf("Server did not respond with a proper nonce header.")
}
- j.nonces = append(j.nonces, nonce)
- return nil
-}
-
-func (j *jws) getNonce() error {
- resp, err := httpHead(j.directoryURL)
- if err != nil {
- return err
- }
-
- return j.getNonceFromResponse(resp)
-}
-
-func (j *jws) Nonce() (string, error) {
- j.Lock()
- defer j.Unlock()
- nonce := ""
- if len(j.nonces) == 0 {
- err := j.getNonce()
- if err != nil {
- return nonce, err
- }
- }
- if len(j.nonces) == 0 {
- return "", fmt.Errorf("Can't get nonce")
- }
- nonce, j.nonces = j.nonces[len(j.nonces)-1], j.nonces[:len(j.nonces)-1]
return nonce, nil
}
diff --git a/vendor/github.com/xenolf/lego/providers/http/memcached/memcached.go b/vendor/github.com/xenolf/lego/providers/http/memcached/memcached.go
index 9c5f6c0b40..9ac8b811da 100644
--- a/vendor/github.com/xenolf/lego/providers/http/memcached/memcached.go
+++ b/vendor/github.com/xenolf/lego/providers/http/memcached/memcached.go
@@ -1,4 +1,5 @@
-// Package webroot implements a HTTP provider for solving the HTTP-01 challenge using web server's root path.
+// Package memcached implements a HTTP provider for solving the HTTP-01 challenge using memcached
+// in combination with a webserver.
package memcached
import (
diff --git a/vendor/golang.org/x/crypto/acme/acme.go b/vendor/golang.org/x/crypto/acme/acme.go
index 8aafada091..8619508e58 100644
--- a/vendor/golang.org/x/crypto/acme/acme.go
+++ b/vendor/golang.org/x/crypto/acme/acme.go
@@ -47,6 +47,10 @@ const LetsEncryptURL = "https://acme-v01.api.letsencrypt.org/directory"
const (
maxChainLen = 5 // max depth and breadth of a certificate chain
maxCertSize = 1 << 20 // max size of a certificate, in bytes
+
+ // Max number of collected nonces kept in memory.
+ // Expect usual peak of 1 or 2.
+ maxNonces = 100
)
// CertOption is an optional argument type for Client methods which manipulate
@@ -108,6 +112,9 @@ type Client struct {
dirMu sync.Mutex // guards writes to dir
dir *Directory // cached result of Client's Discover method
+
+ noncesMu sync.Mutex
+ nonces map[string]struct{} // nonces collected from previous responses
}
// Discover performs ACME server discovery using c.DirectoryURL.
@@ -131,6 +138,7 @@ func (c *Client) Discover(ctx context.Context) (Directory, error) {
return Directory{}, err
}
defer res.Body.Close()
+ c.addNonce(res.Header)
if res.StatusCode != http.StatusOK {
return Directory{}, responseError(res)
}
@@ -192,7 +200,7 @@ func (c *Client) CreateCert(ctx context.Context, csr []byte, exp time.Duration,
req.NotAfter = now.Add(exp).Format(time.RFC3339)
}
- res, err := postJWS(ctx, c.HTTPClient, c.Key, c.dir.CertURL, req)
+ res, err := c.postJWS(ctx, c.Key, c.dir.CertURL, req)
if err != nil {
return nil, "", err
}
@@ -267,7 +275,7 @@ func (c *Client) RevokeCert(ctx context.Context, key crypto.Signer, cert []byte,
if key == nil {
key = c.Key
}
- res, err := postJWS(ctx, c.HTTPClient, key, c.dir.RevokeURL, body)
+ res, err := c.postJWS(ctx, key, c.dir.RevokeURL, body)
if err != nil {
return err
}
@@ -355,7 +363,7 @@ func (c *Client) Authorize(ctx context.Context, domain string) (*Authorization,
Resource: "new-authz",
Identifier: authzID{Type: "dns", Value: domain},
}
- res, err := postJWS(ctx, c.HTTPClient, c.Key, c.dir.AuthzURL, req)
+ res, err := c.postJWS(ctx, c.Key, c.dir.AuthzURL, req)
if err != nil {
return nil, err
}
@@ -413,7 +421,7 @@ func (c *Client) RevokeAuthorization(ctx context.Context, url string) error {
Status: "deactivated",
Delete: true,
}
- res, err := postJWS(ctx, c.HTTPClient, c.Key, url, req)
+ res, err := c.postJWS(ctx, c.Key, url, req)
if err != nil {
return err
}
@@ -519,7 +527,7 @@ func (c *Client) Accept(ctx context.Context, chal *Challenge) (*Challenge, error
Type: chal.Type,
Auth: auth,
}
- res, err := postJWS(ctx, c.HTTPClient, c.Key, chal.URI, req)
+ res, err := c.postJWS(ctx, c.Key, chal.URI, req)
if err != nil {
return nil, err
}
@@ -652,7 +660,7 @@ func (c *Client) doReg(ctx context.Context, url string, typ string, acct *Accoun
req.Contact = acct.Contact
req.Agreement = acct.AgreedTerms
}
- res, err := postJWS(ctx, c.HTTPClient, c.Key, url, req)
+ res, err := c.postJWS(ctx, c.Key, url, req)
if err != nil {
return nil, err
}
@@ -689,6 +697,78 @@ func (c *Client) doReg(ctx context.Context, url string, typ string, acct *Accoun
}, nil
}
+// postJWS signs the body with the given key and POSTs it to the provided url.
+// The body argument must be JSON-serializable.
+func (c *Client) postJWS(ctx context.Context, key crypto.Signer, url string, body interface{}) (*http.Response, error) {
+ nonce, err := c.popNonce(ctx, url)
+ if err != nil {
+ return nil, err
+ }
+ b, err := jwsEncodeJSON(body, key, nonce)
+ if err != nil {
+ return nil, err
+ }
+ res, err := ctxhttp.Post(ctx, c.HTTPClient, url, "application/jose+json", bytes.NewReader(b))
+ if err != nil {
+ return nil, err
+ }
+ c.addNonce(res.Header)
+ return res, nil
+}
+
+// popNonce returns a nonce value previously stored with c.addNonce
+// or fetches a fresh one from the given URL.
+func (c *Client) popNonce(ctx context.Context, url string) (string, error) {
+ c.noncesMu.Lock()
+ defer c.noncesMu.Unlock()
+ if len(c.nonces) == 0 {
+ return fetchNonce(ctx, c.HTTPClient, url)
+ }
+ var nonce string
+ for nonce = range c.nonces {
+ delete(c.nonces, nonce)
+ break
+ }
+ return nonce, nil
+}
+
+// addNonce stores a nonce value found in h (if any) for future use.
+func (c *Client) addNonce(h http.Header) {
+ v := nonceFromHeader(h)
+ if v == "" {
+ return
+ }
+ c.noncesMu.Lock()
+ defer c.noncesMu.Unlock()
+ if len(c.nonces) >= maxNonces {
+ return
+ }
+ if c.nonces == nil {
+ c.nonces = make(map[string]struct{})
+ }
+ c.nonces[v] = struct{}{}
+}
+
+func fetchNonce(ctx context.Context, client *http.Client, url string) (string, error) {
+ resp, err := ctxhttp.Head(ctx, client, url)
+ if err != nil {
+ return "", err
+ }
+ defer resp.Body.Close()
+ nonce := nonceFromHeader(resp.Header)
+ if nonce == "" {
+ if resp.StatusCode > 299 {
+ return "", responseError(resp)
+ }
+ return "", errors.New("acme: nonce not found")
+ }
+ return nonce, nil
+}
+
+func nonceFromHeader(h http.Header) string {
+ return h.Get("Replay-Nonce")
+}
+
func responseCert(ctx context.Context, client *http.Client, res *http.Response, bundle bool) ([][]byte, error) {
b, err := ioutil.ReadAll(io.LimitReader(res.Body, maxCertSize+1))
if err != nil {
@@ -793,33 +873,6 @@ func chainCert(ctx context.Context, client *http.Client, url string, depth int)
return chain, nil
}
-// postJWS signs the body with the given key and POSTs it to the provided url.
-// The body argument must be JSON-serializable.
-func postJWS(ctx context.Context, client *http.Client, key crypto.Signer, url string, body interface{}) (*http.Response, error) {
- nonce, err := fetchNonce(ctx, client, url)
- if err != nil {
- return nil, err
- }
- b, err := jwsEncodeJSON(body, key, nonce)
- if err != nil {
- return nil, err
- }
- return ctxhttp.Post(ctx, client, url, "application/jose+json", bytes.NewReader(b))
-}
-
-func fetchNonce(ctx context.Context, client *http.Client, url string) (string, error) {
- resp, err := ctxhttp.Head(ctx, client, url)
- if err != nil {
- return "", nil
- }
- defer resp.Body.Close()
- enc := resp.Header.Get("replay-nonce")
- if enc == "" {
- return "", errors.New("acme: nonce not found")
- }
- return enc, nil
-}
-
// linkHeader returns URI-Reference values of all Link headers
// with relation-type rel.
// See https://tools.ietf.org/html/rfc5988#section-5 for details.
diff --git a/vendor/golang.org/x/crypto/acme/acme_test.go b/vendor/golang.org/x/crypto/acme/acme_test.go
index 4e618f2929..1205dbb363 100644
--- a/vendor/golang.org/x/crypto/acme/acme_test.go
+++ b/vendor/golang.org/x/crypto/acme/acme_test.go
@@ -45,6 +45,28 @@ func decodeJWSRequest(t *testing.T, v interface{}, r *http.Request) {
}
}
+type jwsHead struct {
+ Alg string
+ Nonce string
+ JWK map[string]string `json:"jwk"`
+}
+
+func decodeJWSHead(r *http.Request) (*jwsHead, error) {
+ var req struct{ Protected string }
+ if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
+ return nil, err
+ }
+ b, err := base64.RawURLEncoding.DecodeString(req.Protected)
+ if err != nil {
+ return nil, err
+ }
+ var head jwsHead
+ if err := json.Unmarshal(b, &head); err != nil {
+ return nil, err
+ }
+ return &head, nil
+}
+
func TestDiscover(t *testing.T) {
const (
reg = "https://example.com/acme/new-reg"
@@ -916,7 +938,30 @@ func TestRevokeCert(t *testing.T) {
}
}
-func TestFetchNonce(t *testing.T) {
+func TestNonce_add(t *testing.T) {
+ var c Client
+ c.addNonce(http.Header{"Replay-Nonce": {"nonce"}})
+ c.addNonce(http.Header{"Replay-Nonce": {}})
+ c.addNonce(http.Header{"Replay-Nonce": {"nonce"}})
+
+ nonces := map[string]struct{}{"nonce": struct{}{}}
+ if !reflect.DeepEqual(c.nonces, nonces) {
+ t.Errorf("c.nonces = %q; want %q", c.nonces, nonces)
+ }
+}
+
+func TestNonce_addMax(t *testing.T) {
+ c := &Client{nonces: make(map[string]struct{})}
+ for i := 0; i < maxNonces; i++ {
+ c.nonces[fmt.Sprintf("%d", i)] = struct{}{}
+ }
+ c.addNonce(http.Header{"Replay-Nonce": {"nonce"}})
+ if n := len(c.nonces); n != maxNonces {
+ t.Errorf("len(c.nonces) = %d; want %d", n, maxNonces)
+ }
+}
+
+func TestNonce_fetch(t *testing.T) {
tests := []struct {
code int
nonce string
@@ -949,6 +994,76 @@ func TestFetchNonce(t *testing.T) {
}
}
+func TestNonce_fetchError(t *testing.T) {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(http.StatusTooManyRequests)
+ }))
+ defer ts.Close()
+ _, err := fetchNonce(context.Background(), http.DefaultClient, ts.URL)
+ e, ok := err.(*Error)
+ if !ok {
+ t.Fatalf("err is %T; want *Error", err)
+ }
+ if e.StatusCode != http.StatusTooManyRequests {
+ t.Errorf("e.StatusCode = %d; want %d", e.StatusCode, http.StatusTooManyRequests)
+ }
+}
+
+func TestNonce_postJWS(t *testing.T) {
+ var count int
+ seen := make(map[string]bool)
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ count++
+ w.Header().Set("replay-nonce", fmt.Sprintf("nonce%d", count))
+ if r.Method == "HEAD" {
+ // We expect the client do a HEAD request
+ // but only to fetch the first nonce.
+ return
+ }
+ // Make client.Authorize happy; we're not testing its result.
+ defer func() {
+ w.WriteHeader(http.StatusCreated)
+ w.Write([]byte(`{"status":"valid"}`))
+ }()
+
+ head, err := decodeJWSHead(r)
+ if err != nil {
+ t.Errorf("decodeJWSHead: %v", err)
+ return
+ }
+ if head.Nonce == "" {
+ t.Error("head.Nonce is empty")
+ return
+ }
+ if seen[head.Nonce] {
+ t.Errorf("nonce is already used: %q", head.Nonce)
+ }
+ seen[head.Nonce] = true
+ }))
+ defer ts.Close()
+
+ client := Client{Key: testKey, dir: &Directory{AuthzURL: ts.URL}}
+ if _, err := client.Authorize(context.Background(), "example.com"); err != nil {
+ t.Errorf("client.Authorize 1: %v", err)
+ }
+ // The second call should not generate another extra HEAD request.
+ if _, err := client.Authorize(context.Background(), "example.com"); err != nil {
+ t.Errorf("client.Authorize 2: %v", err)
+ }
+
+ if count != 3 {
+ t.Errorf("total requests count: %d; want 3", count)
+ }
+ if n := len(client.nonces); n != 1 {
+ t.Errorf("len(client.nonces) = %d; want 1", n)
+ }
+ for k := range seen {
+ if _, exist := client.nonces[k]; exist {
+ t.Errorf("used nonce %q in client.nonces", k)
+ }
+ }
+}
+
func TestLinkHeader(t *testing.T) {
h := http.Header{"Link": {
`;rel="next"`,
diff --git a/vendor/golang.org/x/crypto/acme/autocert/autocert_test.go b/vendor/golang.org/x/crypto/acme/autocert/autocert_test.go
index 4bcd6d532a..7afb213317 100644
--- a/vendor/golang.org/x/crypto/acme/autocert/autocert_test.go
+++ b/vendor/golang.org/x/crypto/acme/autocert/autocert_test.go
@@ -22,6 +22,7 @@ import (
"net/http"
"net/http/httptest"
"reflect"
+ "sync"
"testing"
"time"
@@ -51,26 +52,44 @@ var authzTmpl = template.Must(template.New("authz").Parse(`{
]
}`))
-type memCache map[string][]byte
+type memCache struct {
+ mu sync.Mutex
+ keyData map[string][]byte
+}
-func (m memCache) Get(ctx context.Context, key string) ([]byte, error) {
- v, ok := m[key]
+func (m *memCache) Get(ctx context.Context, key string) ([]byte, error) {
+ m.mu.Lock()
+ defer m.mu.Unlock()
+
+ v, ok := m.keyData[key]
if !ok {
return nil, ErrCacheMiss
}
return v, nil
}
-func (m memCache) Put(ctx context.Context, key string, data []byte) error {
- m[key] = data
+func (m *memCache) Put(ctx context.Context, key string, data []byte) error {
+ m.mu.Lock()
+ defer m.mu.Unlock()
+
+ m.keyData[key] = data
return nil
}
-func (m memCache) Delete(ctx context.Context, key string) error {
- delete(m, key)
+func (m *memCache) Delete(ctx context.Context, key string) error {
+ m.mu.Lock()
+ defer m.mu.Unlock()
+
+ delete(m.keyData, key)
return nil
}
+func newMemCache() *memCache {
+ return &memCache{
+ keyData: make(map[string][]byte),
+ }
+}
+
func dummyCert(pub interface{}, san ...string) ([]byte, error) {
return dateDummyCert(pub, time.Now(), time.Now().Add(90*24*time.Hour), san...)
}
@@ -124,7 +143,7 @@ func TestGetCertificate_trailingDot(t *testing.T) {
func TestGetCertificate_ForceRSA(t *testing.T) {
man := &Manager{
Prompt: AcceptTOS,
- Cache: make(memCache),
+ Cache: newMemCache(),
ForceRSA: true,
}
defer man.stopRenew()
@@ -280,8 +299,7 @@ func testGetCertificate(t *testing.T, man *Manager, domain string, hello *tls.Cl
}
func TestAccountKeyCache(t *testing.T) {
- cache := make(memCache)
- m := Manager{Cache: cache}
+ m := Manager{Cache: newMemCache()}
ctx := context.Background()
k1, err := m.accountKey(ctx)
if err != nil {
@@ -315,8 +333,7 @@ func TestCache(t *testing.T) {
PrivateKey: privKey,
}
- cache := make(memCache)
- man := &Manager{Cache: cache}
+ man := &Manager{Cache: newMemCache()}
defer man.stopRenew()
if err := man.cachePut("example.org", tlscert); err != nil {
t.Fatalf("man.cachePut: %v", err)
diff --git a/vendor/golang.org/x/crypto/acme/autocert/renewal_test.go b/vendor/golang.org/x/crypto/acme/autocert/renewal_test.go
index d1ec52f4d0..10c811ac40 100644
--- a/vendor/golang.org/x/crypto/acme/autocert/renewal_test.go
+++ b/vendor/golang.org/x/crypto/acme/autocert/renewal_test.go
@@ -111,7 +111,7 @@ func TestRenewFromCache(t *testing.T) {
}
man := &Manager{
Prompt: AcceptTOS,
- Cache: make(memCache),
+ Cache: newMemCache(),
RenewBefore: 24 * time.Hour,
Client: &acme.Client{
Key: key,
diff --git a/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s b/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s
index 96a51d524b..784bce6a9c 100644
--- a/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s
+++ b/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s
@@ -54,68 +54,223 @@ DATA ·AVX_c48<>+0x00(SB)/8, $0x0100070605040302
DATA ·AVX_c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a
GLOBL ·AVX_c48<>(SB), (NOPTR+RODATA), $16
-// unfortunately the BYTE representation of VPERMQ must be used
-#define ROUND_AVX2(m0, m1, m2, m3, t, c40, c48) \
- VPADDQ m0, Y0, Y0; \
- VPADDQ Y1, Y0, Y0; \
- VPXOR Y0, Y3, Y3; \
- VPSHUFD $-79, Y3, Y3; \
- VPADDQ Y3, Y2, Y2; \
- VPXOR Y2, Y1, Y1; \
- VPSHUFB c40, Y1, Y1; \
- VPADDQ m1, Y0, Y0; \
- VPADDQ Y1, Y0, Y0; \
- VPXOR Y0, Y3, Y3; \
- VPSHUFB c48, Y3, Y3; \
- VPADDQ Y3, Y2, Y2; \
- VPXOR Y2, Y1, Y1; \
- VPADDQ Y1, Y1, t; \
- VPSRLQ $63, Y1, Y1; \
- VPXOR t, Y1, Y1; \
- BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x39 \ // VPERMQ 0x39, Y1, Y1
- BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xd2; BYTE $0x4e \ // VPERMQ 0x4e, Y2, Y2
- BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x93 \ // VPERMQ 0x93, Y3, Y3
- VPADDQ m2, Y0, Y0; \
- VPADDQ Y1, Y0, Y0; \
- VPXOR Y0, Y3, Y3; \
- VPSHUFD $-79, Y3, Y3; \
- VPADDQ Y3, Y2, Y2; \
- VPXOR Y2, Y1, Y1; \
- VPSHUFB c40, Y1, Y1; \
- VPADDQ m3, Y0, Y0; \
- VPADDQ Y1, Y0, Y0; \
- VPXOR Y0, Y3, Y3; \
- VPSHUFB c48, Y3, Y3; \
- VPADDQ Y3, Y2, Y2; \
- VPXOR Y2, Y1, Y1; \
- VPADDQ Y1, Y1, t; \
- VPSRLQ $63, Y1, Y1; \
- VPXOR t, Y1, Y1; \
- BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x39 \ // VPERMQ 0x39, Y3, Y3
- BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xd2; BYTE $0x4e \ // VPERMQ 0x4e, Y2, Y2
- BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x93 \ // VPERMQ 0x93, Y1, Y1
+#define VPERMQ_0x39_Y1_Y1 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x39
+#define VPERMQ_0x93_Y1_Y1 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x93
+#define VPERMQ_0x4E_Y2_Y2 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xd2; BYTE $0x4e
+#define VPERMQ_0x93_Y3_Y3 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x93
+#define VPERMQ_0x39_Y3_Y3 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x39
-// load msg into Y12, Y13, Y14, Y15
-#define LOAD_MSG_AVX2(src, i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15) \
- MOVQ i0*8(src), X12; \
- PINSRQ $1, i1*8(src), X12; \
- MOVQ i2*8(src), X11; \
- PINSRQ $1, i3*8(src), X11; \
- VINSERTI128 $1, X11, Y12, Y12; \
- MOVQ i4*8(src), X13; \
- PINSRQ $1, i5*8(src), X13; \
- MOVQ i6*8(src), X11; \
- PINSRQ $1, i7*8(src), X11; \
- VINSERTI128 $1, X11, Y13, Y13; \
- MOVQ i8*8(src), X14; \
- PINSRQ $1, i9*8(src), X14; \
- MOVQ i10*8(src), X11; \
- PINSRQ $1, i11*8(src), X11; \
+#define ROUND_AVX2(m0, m1, m2, m3, t, c40, c48) \
+ VPADDQ m0, Y0, Y0; \
+ VPADDQ Y1, Y0, Y0; \
+ VPXOR Y0, Y3, Y3; \
+ VPSHUFD $-79, Y3, Y3; \
+ VPADDQ Y3, Y2, Y2; \
+ VPXOR Y2, Y1, Y1; \
+ VPSHUFB c40, Y1, Y1; \
+ VPADDQ m1, Y0, Y0; \
+ VPADDQ Y1, Y0, Y0; \
+ VPXOR Y0, Y3, Y3; \
+ VPSHUFB c48, Y3, Y3; \
+ VPADDQ Y3, Y2, Y2; \
+ VPXOR Y2, Y1, Y1; \
+ VPADDQ Y1, Y1, t; \
+ VPSRLQ $63, Y1, Y1; \
+ VPXOR t, Y1, Y1; \
+ VPERMQ_0x39_Y1_Y1; \
+ VPERMQ_0x4E_Y2_Y2; \
+ VPERMQ_0x93_Y3_Y3; \
+ VPADDQ m2, Y0, Y0; \
+ VPADDQ Y1, Y0, Y0; \
+ VPXOR Y0, Y3, Y3; \
+ VPSHUFD $-79, Y3, Y3; \
+ VPADDQ Y3, Y2, Y2; \
+ VPXOR Y2, Y1, Y1; \
+ VPSHUFB c40, Y1, Y1; \
+ VPADDQ m3, Y0, Y0; \
+ VPADDQ Y1, Y0, Y0; \
+ VPXOR Y0, Y3, Y3; \
+ VPSHUFB c48, Y3, Y3; \
+ VPADDQ Y3, Y2, Y2; \
+ VPXOR Y2, Y1, Y1; \
+ VPADDQ Y1, Y1, t; \
+ VPSRLQ $63, Y1, Y1; \
+ VPXOR t, Y1, Y1; \
+ VPERMQ_0x39_Y3_Y3; \
+ VPERMQ_0x4E_Y2_Y2; \
+ VPERMQ_0x93_Y1_Y1
+
+#define VMOVQ_SI_X11_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x1E
+#define VMOVQ_SI_X12_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x26
+#define VMOVQ_SI_X13_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x2E
+#define VMOVQ_SI_X14_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x36
+#define VMOVQ_SI_X15_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x3E
+
+#define VMOVQ_SI_X11(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x5E; BYTE $n
+#define VMOVQ_SI_X12(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x66; BYTE $n
+#define VMOVQ_SI_X13(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x6E; BYTE $n
+#define VMOVQ_SI_X14(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x76; BYTE $n
+#define VMOVQ_SI_X15(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x7E; BYTE $n
+
+#define VPINSRQ_1_SI_X11_0 BYTE $0xC4; BYTE $0x63; BYTE $0xA1; BYTE $0x22; BYTE $0x1E; BYTE $0x01
+#define VPINSRQ_1_SI_X12_0 BYTE $0xC4; BYTE $0x63; BYTE $0x99; BYTE $0x22; BYTE $0x26; BYTE $0x01
+#define VPINSRQ_1_SI_X13_0 BYTE $0xC4; BYTE $0x63; BYTE $0x91; BYTE $0x22; BYTE $0x2E; BYTE $0x01
+#define VPINSRQ_1_SI_X14_0 BYTE $0xC4; BYTE $0x63; BYTE $0x89; BYTE $0x22; BYTE $0x36; BYTE $0x01
+#define VPINSRQ_1_SI_X15_0 BYTE $0xC4; BYTE $0x63; BYTE $0x81; BYTE $0x22; BYTE $0x3E; BYTE $0x01
+
+#define VPINSRQ_1_SI_X11(n) BYTE $0xC4; BYTE $0x63; BYTE $0xA1; BYTE $0x22; BYTE $0x5E; BYTE $n; BYTE $0x01
+#define VPINSRQ_1_SI_X12(n) BYTE $0xC4; BYTE $0x63; BYTE $0x99; BYTE $0x22; BYTE $0x66; BYTE $n; BYTE $0x01
+#define VPINSRQ_1_SI_X13(n) BYTE $0xC4; BYTE $0x63; BYTE $0x91; BYTE $0x22; BYTE $0x6E; BYTE $n; BYTE $0x01
+#define VPINSRQ_1_SI_X14(n) BYTE $0xC4; BYTE $0x63; BYTE $0x89; BYTE $0x22; BYTE $0x76; BYTE $n; BYTE $0x01
+#define VPINSRQ_1_SI_X15(n) BYTE $0xC4; BYTE $0x63; BYTE $0x81; BYTE $0x22; BYTE $0x7E; BYTE $n; BYTE $0x01
+
+#define VMOVQ_R8_X15 BYTE $0xC4; BYTE $0x41; BYTE $0xF9; BYTE $0x6E; BYTE $0xF8
+#define VPINSRQ_1_R9_X15 BYTE $0xC4; BYTE $0x43; BYTE $0x81; BYTE $0x22; BYTE $0xF9; BYTE $0x01
+
+// load msg: Y12 = (i0, i1, i2, i3)
+// i0, i1, i2, i3 must not be 0
+#define LOAD_MSG_AVX2_Y12(i0, i1, i2, i3) \
+ VMOVQ_SI_X12(i0*8); \
+ VMOVQ_SI_X11(i2*8); \
+ VPINSRQ_1_SI_X12(i1*8); \
+ VPINSRQ_1_SI_X11(i3*8); \
+ VINSERTI128 $1, X11, Y12, Y12
+
+// load msg: Y13 = (i0, i1, i2, i3)
+// i0, i1, i2, i3 must not be 0
+#define LOAD_MSG_AVX2_Y13(i0, i1, i2, i3) \
+ VMOVQ_SI_X13(i0*8); \
+ VMOVQ_SI_X11(i2*8); \
+ VPINSRQ_1_SI_X13(i1*8); \
+ VPINSRQ_1_SI_X11(i3*8); \
+ VINSERTI128 $1, X11, Y13, Y13
+
+// load msg: Y14 = (i0, i1, i2, i3)
+// i0, i1, i2, i3 must not be 0
+#define LOAD_MSG_AVX2_Y14(i0, i1, i2, i3) \
+ VMOVQ_SI_X14(i0*8); \
+ VMOVQ_SI_X11(i2*8); \
+ VPINSRQ_1_SI_X14(i1*8); \
+ VPINSRQ_1_SI_X11(i3*8); \
+ VINSERTI128 $1, X11, Y14, Y14
+
+// load msg: Y15 = (i0, i1, i2, i3)
+// i0, i1, i2, i3 must not be 0
+#define LOAD_MSG_AVX2_Y15(i0, i1, i2, i3) \
+ VMOVQ_SI_X15(i0*8); \
+ VMOVQ_SI_X11(i2*8); \
+ VPINSRQ_1_SI_X15(i1*8); \
+ VPINSRQ_1_SI_X11(i3*8); \
+ VINSERTI128 $1, X11, Y15, Y15
+
+#define LOAD_MSG_AVX2_0_2_4_6_1_3_5_7_8_10_12_14_9_11_13_15() \
+ VMOVQ_SI_X12_0; \
+ VMOVQ_SI_X11(4*8); \
+ VPINSRQ_1_SI_X12(2*8); \
+ VPINSRQ_1_SI_X11(6*8); \
+ VINSERTI128 $1, X11, Y12, Y12; \
+ LOAD_MSG_AVX2_Y13(1, 3, 5, 7); \
+ LOAD_MSG_AVX2_Y14(8, 10, 12, 14); \
+ LOAD_MSG_AVX2_Y15(9, 11, 13, 15)
+
+#define LOAD_MSG_AVX2_14_4_9_13_10_8_15_6_1_0_11_5_12_2_7_3() \
+ LOAD_MSG_AVX2_Y12(14, 4, 9, 13); \
+ LOAD_MSG_AVX2_Y13(10, 8, 15, 6); \
+ VMOVQ_SI_X11(11*8); \
+ VPSHUFD $0x4E, 0*8(SI), X14; \
+ VPINSRQ_1_SI_X11(5*8); \
VINSERTI128 $1, X11, Y14, Y14; \
- MOVQ i12*8(src), X15; \
- PINSRQ $1, i13*8(src), X15; \
- MOVQ i14*8(src), X11; \
- PINSRQ $1, i15*8(src), X11; \
+ LOAD_MSG_AVX2_Y15(12, 2, 7, 3)
+
+#define LOAD_MSG_AVX2_11_12_5_15_8_0_2_13_10_3_7_9_14_6_1_4() \
+ VMOVQ_SI_X11(5*8); \
+ VMOVDQU 11*8(SI), X12; \
+ VPINSRQ_1_SI_X11(15*8); \
+ VINSERTI128 $1, X11, Y12, Y12; \
+ VMOVQ_SI_X13(8*8); \
+ VMOVQ_SI_X11(2*8); \
+ VPINSRQ_1_SI_X13_0; \
+ VPINSRQ_1_SI_X11(13*8); \
+ VINSERTI128 $1, X11, Y13, Y13; \
+ LOAD_MSG_AVX2_Y14(10, 3, 7, 9); \
+ LOAD_MSG_AVX2_Y15(14, 6, 1, 4)
+
+#define LOAD_MSG_AVX2_7_3_13_11_9_1_12_14_2_5_4_15_6_10_0_8() \
+ LOAD_MSG_AVX2_Y12(7, 3, 13, 11); \
+ LOAD_MSG_AVX2_Y13(9, 1, 12, 14); \
+ LOAD_MSG_AVX2_Y14(2, 5, 4, 15); \
+ VMOVQ_SI_X15(6*8); \
+ VMOVQ_SI_X11_0; \
+ VPINSRQ_1_SI_X15(10*8); \
+ VPINSRQ_1_SI_X11(8*8); \
+ VINSERTI128 $1, X11, Y15, Y15
+
+#define LOAD_MSG_AVX2_9_5_2_10_0_7_4_15_14_11_6_3_1_12_8_13() \
+ LOAD_MSG_AVX2_Y12(9, 5, 2, 10); \
+ VMOVQ_SI_X13_0; \
+ VMOVQ_SI_X11(4*8); \
+ VPINSRQ_1_SI_X13(7*8); \
+ VPINSRQ_1_SI_X11(15*8); \
+ VINSERTI128 $1, X11, Y13, Y13; \
+ LOAD_MSG_AVX2_Y14(14, 11, 6, 3); \
+ LOAD_MSG_AVX2_Y15(1, 12, 8, 13)
+
+#define LOAD_MSG_AVX2_2_6_0_8_12_10_11_3_4_7_15_1_13_5_14_9() \
+ VMOVQ_SI_X12(2*8); \
+ VMOVQ_SI_X11_0; \
+ VPINSRQ_1_SI_X12(6*8); \
+ VPINSRQ_1_SI_X11(8*8); \
+ VINSERTI128 $1, X11, Y12, Y12; \
+ LOAD_MSG_AVX2_Y13(12, 10, 11, 3); \
+ LOAD_MSG_AVX2_Y14(4, 7, 15, 1); \
+ LOAD_MSG_AVX2_Y15(13, 5, 14, 9)
+
+#define LOAD_MSG_AVX2_12_1_14_4_5_15_13_10_0_6_9_8_7_3_2_11() \
+ LOAD_MSG_AVX2_Y12(12, 1, 14, 4); \
+ LOAD_MSG_AVX2_Y13(5, 15, 13, 10); \
+ VMOVQ_SI_X14_0; \
+ VPSHUFD $0x4E, 8*8(SI), X11; \
+ VPINSRQ_1_SI_X14(6*8); \
+ VINSERTI128 $1, X11, Y14, Y14; \
+ LOAD_MSG_AVX2_Y15(7, 3, 2, 11)
+
+#define LOAD_MSG_AVX2_13_7_12_3_11_14_1_9_5_15_8_2_0_4_6_10() \
+ LOAD_MSG_AVX2_Y12(13, 7, 12, 3); \
+ LOAD_MSG_AVX2_Y13(11, 14, 1, 9); \
+ LOAD_MSG_AVX2_Y14(5, 15, 8, 2); \
+ VMOVQ_SI_X15_0; \
+ VMOVQ_SI_X11(6*8); \
+ VPINSRQ_1_SI_X15(4*8); \
+ VPINSRQ_1_SI_X11(10*8); \
+ VINSERTI128 $1, X11, Y15, Y15
+
+#define LOAD_MSG_AVX2_6_14_11_0_15_9_3_8_12_13_1_10_2_7_4_5() \
+ VMOVQ_SI_X12(6*8); \
+ VMOVQ_SI_X11(11*8); \
+ VPINSRQ_1_SI_X12(14*8); \
+ VPINSRQ_1_SI_X11_0; \
+ VINSERTI128 $1, X11, Y12, Y12; \
+ LOAD_MSG_AVX2_Y13(15, 9, 3, 8); \
+ VMOVQ_SI_X11(1*8); \
+ VMOVDQU 12*8(SI), X14; \
+ VPINSRQ_1_SI_X11(10*8); \
+ VINSERTI128 $1, X11, Y14, Y14; \
+ VMOVQ_SI_X15(2*8); \
+ VMOVDQU 4*8(SI), X11; \
+ VPINSRQ_1_SI_X15(7*8); \
+ VINSERTI128 $1, X11, Y15, Y15
+
+#define LOAD_MSG_AVX2_10_8_7_1_2_4_6_5_15_9_3_13_11_14_12_0() \
+ LOAD_MSG_AVX2_Y12(10, 8, 7, 1); \
+ VMOVQ_SI_X13(2*8); \
+ VPSHUFD $0x4E, 5*8(SI), X11; \
+ VPINSRQ_1_SI_X13(4*8); \
+ VINSERTI128 $1, X11, Y13, Y13; \
+ LOAD_MSG_AVX2_Y14(15, 9, 3, 13); \
+ VMOVQ_SI_X15(11*8); \
+ VMOVQ_SI_X11(12*8); \
+ VPINSRQ_1_SI_X15(14*8); \
+ VPINSRQ_1_SI_X11_0; \
VINSERTI128 $1, X11, Y15, Y15
// func hashBlocksAVX2(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte)
@@ -162,34 +317,34 @@ noinc:
VMOVDQA Y6, Y2
VPXOR 0(SP), Y7, Y3
- LOAD_MSG_AVX2(SI, 0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15)
+ LOAD_MSG_AVX2_0_2_4_6_1_3_5_7_8_10_12_14_9_11_13_15()
VMOVDQA Y12, 32(SP)
VMOVDQA Y13, 64(SP)
VMOVDQA Y14, 96(SP)
VMOVDQA Y15, 128(SP)
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
- LOAD_MSG_AVX2(SI, 14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3)
+ LOAD_MSG_AVX2_14_4_9_13_10_8_15_6_1_0_11_5_12_2_7_3()
VMOVDQA Y12, 160(SP)
VMOVDQA Y13, 192(SP)
VMOVDQA Y14, 224(SP)
VMOVDQA Y15, 256(SP)
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
- LOAD_MSG_AVX2(SI, 11, 12, 5, 15, 8, 0, 2, 13, 10, 3, 7, 9, 14, 6, 1, 4)
+ LOAD_MSG_AVX2_11_12_5_15_8_0_2_13_10_3_7_9_14_6_1_4()
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
- LOAD_MSG_AVX2(SI, 7, 3, 13, 11, 9, 1, 12, 14, 2, 5, 4, 15, 6, 10, 0, 8)
+ LOAD_MSG_AVX2_7_3_13_11_9_1_12_14_2_5_4_15_6_10_0_8()
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
- LOAD_MSG_AVX2(SI, 9, 5, 2, 10, 0, 7, 4, 15, 14, 11, 6, 3, 1, 12, 8, 13)
+ LOAD_MSG_AVX2_9_5_2_10_0_7_4_15_14_11_6_3_1_12_8_13()
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
- LOAD_MSG_AVX2(SI, 2, 6, 0, 8, 12, 10, 11, 3, 4, 7, 15, 1, 13, 5, 14, 9)
+ LOAD_MSG_AVX2_2_6_0_8_12_10_11_3_4_7_15_1_13_5_14_9()
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
- LOAD_MSG_AVX2(SI, 12, 1, 14, 4, 5, 15, 13, 10, 0, 6, 9, 8, 7, 3, 2, 11)
+ LOAD_MSG_AVX2_12_1_14_4_5_15_13_10_0_6_9_8_7_3_2_11()
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
- LOAD_MSG_AVX2(SI, 13, 7, 12, 3, 11, 14, 1, 9, 5, 15, 8, 2, 0, 4, 6, 10)
+ LOAD_MSG_AVX2_13_7_12_3_11_14_1_9_5_15_8_2_0_4_6_10()
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
- LOAD_MSG_AVX2(SI, 6, 14, 11, 0, 15, 9, 3, 8, 12, 13, 1, 10, 2, 7, 4, 5)
+ LOAD_MSG_AVX2_6_14_11_0_15_9_3_8_12_13_1_10_2_7_4_5()
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
- LOAD_MSG_AVX2(SI, 10, 8, 7, 1, 2, 4, 6, 5, 15, 9, 3, 13, 11, 14, 12, 0)
+ LOAD_MSG_AVX2_10_8_7_1_2_4_6_5_15_9_3_13_11_14_12_0()
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
ROUND_AVX2(32(SP), 64(SP), 96(SP), 128(SP), Y10, Y4, Y5)
@@ -209,56 +364,55 @@ noinc:
VMOVDQU Y8, 0(AX)
VMOVDQU Y9, 32(AX)
+ VZEROUPPER
MOVQ DX, SP
RET
-// unfortunately the BYTE representation of VPUNPCKLQDQ and VPUNPCKHQDQ must be used
-#define VPUNPCKLQDQ_X8_X8_X10 BYTE $0xC4; BYTE $0x41; BYTE $0x39; BYTE $0x6C; BYTE $0xD0
-#define VPUNPCKHQDQ_X7_X10_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xF2
-#define VPUNPCKLQDQ_X7_X7_X10 BYTE $0xC5; BYTE $0x41; BYTE $0x6C; BYTE $0xD7
-#define VPUNPCKHQDQ_X8_X10_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x39; BYTE $0x6D; BYTE $0xFA
-#define VPUNPCKLQDQ_X3_X3_X10 BYTE $0xC5; BYTE $0x61; BYTE $0x6C; BYTE $0xD3
-#define VPUNPCKHQDQ_X2_X10_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x69; BYTE $0x6D; BYTE $0xD2
-#define VPUNPCKLQDQ_X9_X9_X10 BYTE $0xC4; BYTE $0x41; BYTE $0x31; BYTE $0x6C; BYTE $0xD1
-#define VPUNPCKHQDQ_X3_X10_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xDA
-#define VPUNPCKLQDQ_X2_X2_X10 BYTE $0xC5; BYTE $0x69; BYTE $0x6C; BYTE $0xD2
-#define VPUNPCKHQDQ_X3_X10_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xD2
-#define VPUNPCKHQDQ_X8_X10_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x39; BYTE $0x6D; BYTE $0xDA
-#define VPUNPCKHQDQ_X6_X10_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x49; BYTE $0x6D; BYTE $0xF2
-#define VPUNPCKHQDQ_X7_X10_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xFA
+#define VPUNPCKLQDQ_X2_X2_X15 BYTE $0xC5; BYTE $0x69; BYTE $0x6C; BYTE $0xFA
+#define VPUNPCKLQDQ_X3_X3_X15 BYTE $0xC5; BYTE $0x61; BYTE $0x6C; BYTE $0xFB
+#define VPUNPCKLQDQ_X7_X7_X15 BYTE $0xC5; BYTE $0x41; BYTE $0x6C; BYTE $0xFF
+#define VPUNPCKLQDQ_X13_X13_X15 BYTE $0xC4; BYTE $0x41; BYTE $0x11; BYTE $0x6C; BYTE $0xFD
+#define VPUNPCKLQDQ_X14_X14_X15 BYTE $0xC4; BYTE $0x41; BYTE $0x09; BYTE $0x6C; BYTE $0xFE
+
+#define VPUNPCKHQDQ_X15_X2_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x69; BYTE $0x6D; BYTE $0xD7
+#define VPUNPCKHQDQ_X15_X3_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xDF
+#define VPUNPCKHQDQ_X15_X6_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x49; BYTE $0x6D; BYTE $0xF7
+#define VPUNPCKHQDQ_X15_X7_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xFF
+#define VPUNPCKHQDQ_X15_X3_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xD7
+#define VPUNPCKHQDQ_X15_X7_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xF7
+#define VPUNPCKHQDQ_X15_X13_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x11; BYTE $0x6D; BYTE $0xDF
+#define VPUNPCKHQDQ_X15_X13_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x11; BYTE $0x6D; BYTE $0xFF
-// shuffle X2 and X6 using the temp registers X8, X9, X10
#define SHUFFLE_AVX() \
- VMOVDQA X4, X9; \
- VMOVDQA X5, X4; \
- VMOVDQA X9, X5; \
- VMOVDQA X6, X8; \
- VPUNPCKLQDQ_X8_X8_X10; \
- VPUNPCKHQDQ_X7_X10_X6; \
- VPUNPCKLQDQ_X7_X7_X10; \
- VPUNPCKHQDQ_X8_X10_X7; \
- VPUNPCKLQDQ_X3_X3_X10; \
- VMOVDQA X2, X9; \
- VPUNPCKHQDQ_X2_X10_X2; \
- VPUNPCKLQDQ_X9_X9_X10; \
- VPUNPCKHQDQ_X3_X10_X3; \
+ VMOVDQA X6, X13; \
+ VMOVDQA X2, X14; \
+ VMOVDQA X4, X6; \
+ VPUNPCKLQDQ_X13_X13_X15; \
+ VMOVDQA X5, X4; \
+ VMOVDQA X6, X5; \
+ VPUNPCKHQDQ_X15_X7_X6; \
+ VPUNPCKLQDQ_X7_X7_X15; \
+ VPUNPCKHQDQ_X15_X13_X7; \
+ VPUNPCKLQDQ_X3_X3_X15; \
+ VPUNPCKHQDQ_X15_X2_X2; \
+ VPUNPCKLQDQ_X14_X14_X15; \
+ VPUNPCKHQDQ_X15_X3_X3; \
-// inverse shuffle X2 and X6 using the temp registers X8, X9, X10
#define SHUFFLE_AVX_INV() \
- VMOVDQA X4, X9; \
- VMOVDQA X5, X4; \
- VMOVDQA X9, X5; \
- VMOVDQA X2, X8; \
- VPUNPCKLQDQ_X2_X2_X10; \
- VPUNPCKHQDQ_X3_X10_X2; \
- VPUNPCKLQDQ_X3_X3_X10; \
- VPUNPCKHQDQ_X8_X10_X3; \
- VPUNPCKLQDQ_X7_X7_X10; \
- VMOVDQA X6, X9; \
- VPUNPCKHQDQ_X6_X10_X6; \
- VPUNPCKLQDQ_X9_X9_X10; \
- VPUNPCKHQDQ_X7_X10_X7; \
+ VMOVDQA X2, X13; \
+ VMOVDQA X4, X14; \
+ VPUNPCKLQDQ_X2_X2_X15; \
+ VMOVDQA X5, X4; \
+ VPUNPCKHQDQ_X15_X3_X2; \
+ VMOVDQA X14, X5; \
+ VPUNPCKLQDQ_X3_X3_X15; \
+ VMOVDQA X6, X14; \
+ VPUNPCKHQDQ_X15_X13_X3; \
+ VPUNPCKLQDQ_X7_X7_X15; \
+ VPUNPCKHQDQ_X15_X6_X6; \
+ VPUNPCKLQDQ_X14_X14_X15; \
+ VPUNPCKHQDQ_X15_X7_X7; \
#define HALF_ROUND_AVX(v0, v1, v2, v3, v4, v5, v6, v7, m0, m1, m2, m3, t0, c40, c48) \
VPADDQ m0, v0, v0; \
@@ -294,28 +448,133 @@ noinc:
VPSRLQ $63, v3, v3; \
VPXOR t0, v3, v3
-// unfortunately the BYTE representation of VPINSRQ must be used
-#define VPINSRQ_1_R10_X8_X8 BYTE $0xC4; BYTE $0x43; BYTE $0xB9; BYTE $0x22; BYTE $0xC2; BYTE $0x01
-#define VPINSRQ_1_R11_X9_X9 BYTE $0xC4; BYTE $0x43; BYTE $0xB1; BYTE $0x22; BYTE $0xCB; BYTE $0x01
-#define VPINSRQ_1_R12_X10_X10 BYTE $0xC4; BYTE $0x43; BYTE $0xA9; BYTE $0x22; BYTE $0xD4; BYTE $0x01
-#define VPINSRQ_1_R13_X11_X11 BYTE $0xC4; BYTE $0x43; BYTE $0xA1; BYTE $0x22; BYTE $0xDD; BYTE $0x01
+// load msg: X12 = (i0, i1), X13 = (i2, i3), X14 = (i4, i5), X15 = (i6, i7)
+// i0, i1, i2, i3, i4, i5, i6, i7 must not be 0
+#define LOAD_MSG_AVX(i0, i1, i2, i3, i4, i5, i6, i7) \
+ VMOVQ_SI_X12(i0*8); \
+ VMOVQ_SI_X13(i2*8); \
+ VMOVQ_SI_X14(i4*8); \
+ VMOVQ_SI_X15(i6*8); \
+ VPINSRQ_1_SI_X12(i1*8); \
+ VPINSRQ_1_SI_X13(i3*8); \
+ VPINSRQ_1_SI_X14(i5*8); \
+ VPINSRQ_1_SI_X15(i7*8)
-#define VPINSRQ_1_R9_X8_X8 BYTE $0xC4; BYTE $0x43; BYTE $0xB9; BYTE $0x22; BYTE $0xC1; BYTE $0x01
+// load msg: X12 = (0, 2), X13 = (4, 6), X14 = (1, 3), X15 = (5, 7)
+#define LOAD_MSG_AVX_0_2_4_6_1_3_5_7() \
+ VMOVQ_SI_X12_0; \
+ VMOVQ_SI_X13(4*8); \
+ VMOVQ_SI_X14(1*8); \
+ VMOVQ_SI_X15(5*8); \
+ VPINSRQ_1_SI_X12(2*8); \
+ VPINSRQ_1_SI_X13(6*8); \
+ VPINSRQ_1_SI_X14(3*8); \
+ VPINSRQ_1_SI_X15(7*8)
-// load src into X8, X9, X10 and X11 using R10, R11, R12 and R13 for temp registers
-#define LOAD_MSG_AVX(src, i0, i1, i2, i3, i4, i5, i6, i7) \
- MOVQ i0*8(src), X8; \
- MOVQ i1*8(src), R10; \
- MOVQ i2*8(src), X9; \
- MOVQ i3*8(src), R11; \
- MOVQ i4*8(src), X10; \
- MOVQ i5*8(src), R12; \
- MOVQ i6*8(src), X11; \
- MOVQ i7*8(src), R13; \
- VPINSRQ_1_R10_X8_X8; \
- VPINSRQ_1_R11_X9_X9; \
- VPINSRQ_1_R12_X10_X10; \
- VPINSRQ_1_R13_X11_X11
+// load msg: X12 = (1, 0), X13 = (11, 5), X14 = (12, 2), X15 = (7, 3)
+#define LOAD_MSG_AVX_1_0_11_5_12_2_7_3() \
+ VPSHUFD $0x4E, 0*8(SI), X12; \
+ VMOVQ_SI_X13(11*8); \
+ VMOVQ_SI_X14(12*8); \
+ VMOVQ_SI_X15(7*8); \
+ VPINSRQ_1_SI_X13(5*8); \
+ VPINSRQ_1_SI_X14(2*8); \
+ VPINSRQ_1_SI_X15(3*8)
+
+// load msg: X12 = (11, 12), X13 = (5, 15), X14 = (8, 0), X15 = (2, 13)
+#define LOAD_MSG_AVX_11_12_5_15_8_0_2_13() \
+ VMOVDQU 11*8(SI), X12; \
+ VMOVQ_SI_X13(5*8); \
+ VMOVQ_SI_X14(8*8); \
+ VMOVQ_SI_X15(2*8); \
+ VPINSRQ_1_SI_X13(15*8); \
+ VPINSRQ_1_SI_X14_0; \
+ VPINSRQ_1_SI_X15(13*8)
+
+// load msg: X12 = (2, 5), X13 = (4, 15), X14 = (6, 10), X15 = (0, 8)
+#define LOAD_MSG_AVX_2_5_4_15_6_10_0_8() \
+ VMOVQ_SI_X12(2*8); \
+ VMOVQ_SI_X13(4*8); \
+ VMOVQ_SI_X14(6*8); \
+ VMOVQ_SI_X15_0; \
+ VPINSRQ_1_SI_X12(5*8); \
+ VPINSRQ_1_SI_X13(15*8); \
+ VPINSRQ_1_SI_X14(10*8); \
+ VPINSRQ_1_SI_X15(8*8)
+
+// load msg: X12 = (9, 5), X13 = (2, 10), X14 = (0, 7), X15 = (4, 15)
+#define LOAD_MSG_AVX_9_5_2_10_0_7_4_15() \
+ VMOVQ_SI_X12(9*8); \
+ VMOVQ_SI_X13(2*8); \
+ VMOVQ_SI_X14_0; \
+ VMOVQ_SI_X15(4*8); \
+ VPINSRQ_1_SI_X12(5*8); \
+ VPINSRQ_1_SI_X13(10*8); \
+ VPINSRQ_1_SI_X14(7*8); \
+ VPINSRQ_1_SI_X15(15*8)
+
+// load msg: X12 = (2, 6), X13 = (0, 8), X14 = (12, 10), X15 = (11, 3)
+#define LOAD_MSG_AVX_2_6_0_8_12_10_11_3() \
+ VMOVQ_SI_X12(2*8); \
+ VMOVQ_SI_X13_0; \
+ VMOVQ_SI_X14(12*8); \
+ VMOVQ_SI_X15(11*8); \
+ VPINSRQ_1_SI_X12(6*8); \
+ VPINSRQ_1_SI_X13(8*8); \
+ VPINSRQ_1_SI_X14(10*8); \
+ VPINSRQ_1_SI_X15(3*8)
+
+// load msg: X12 = (0, 6), X13 = (9, 8), X14 = (7, 3), X15 = (2, 11)
+#define LOAD_MSG_AVX_0_6_9_8_7_3_2_11() \
+ MOVQ 0*8(SI), X12; \
+ VPSHUFD $0x4E, 8*8(SI), X13; \
+ MOVQ 7*8(SI), X14; \
+ MOVQ 2*8(SI), X15; \
+ VPINSRQ_1_SI_X12(6*8); \
+ VPINSRQ_1_SI_X14(3*8); \
+ VPINSRQ_1_SI_X15(11*8)
+
+// load msg: X12 = (6, 14), X13 = (11, 0), X14 = (15, 9), X15 = (3, 8)
+#define LOAD_MSG_AVX_6_14_11_0_15_9_3_8() \
+ MOVQ 6*8(SI), X12; \
+ MOVQ 11*8(SI), X13; \
+ MOVQ 15*8(SI), X14; \
+ MOVQ 3*8(SI), X15; \
+ VPINSRQ_1_SI_X12(14*8); \
+ VPINSRQ_1_SI_X13_0; \
+ VPINSRQ_1_SI_X14(9*8); \
+ VPINSRQ_1_SI_X15(8*8)
+
+// load msg: X12 = (5, 15), X13 = (8, 2), X14 = (0, 4), X15 = (6, 10)
+#define LOAD_MSG_AVX_5_15_8_2_0_4_6_10() \
+ MOVQ 5*8(SI), X12; \
+ MOVQ 8*8(SI), X13; \
+ MOVQ 0*8(SI), X14; \
+ MOVQ 6*8(SI), X15; \
+ VPINSRQ_1_SI_X12(15*8); \
+ VPINSRQ_1_SI_X13(2*8); \
+ VPINSRQ_1_SI_X14(4*8); \
+ VPINSRQ_1_SI_X15(10*8)
+
+// load msg: X12 = (12, 13), X13 = (1, 10), X14 = (2, 7), X15 = (4, 5)
+#define LOAD_MSG_AVX_12_13_1_10_2_7_4_5() \
+ VMOVDQU 12*8(SI), X12; \
+ MOVQ 1*8(SI), X13; \
+ MOVQ 2*8(SI), X14; \
+ VPINSRQ_1_SI_X13(10*8); \
+ VPINSRQ_1_SI_X14(7*8); \
+ VMOVDQU 4*8(SI), X15
+
+// load msg: X12 = (15, 9), X13 = (3, 13), X14 = (11, 14), X15 = (12, 0)
+#define LOAD_MSG_AVX_15_9_3_13_11_14_12_0() \
+ MOVQ 15*8(SI), X12; \
+ MOVQ 3*8(SI), X13; \
+ MOVQ 11*8(SI), X14; \
+ MOVQ 12*8(SI), X15; \
+ VPINSRQ_1_SI_X12(9*8); \
+ VPINSRQ_1_SI_X13(13*8); \
+ VPINSRQ_1_SI_X14(14*8); \
+ VPINSRQ_1_SI_X15_0
// func hashBlocksAVX(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte)
TEXT ·hashBlocksAVX(SB), 4, $288-48 // frame size = 272 + 16 byte alignment
@@ -331,15 +590,17 @@ TEXT ·hashBlocksAVX(SB), 4, $288-48 // frame size = 272 + 16 byte alignment
ANDQ $~15, R9
MOVQ R9, SP
- MOVOU ·AVX_c40<>(SB), X13
- MOVOU ·AVX_c48<>(SB), X14
+ VMOVDQU ·AVX_c40<>(SB), X0
+ VMOVDQU ·AVX_c48<>(SB), X1
+ VMOVDQA X0, X8
+ VMOVDQA X1, X9
VMOVDQU ·AVX_iv3<>(SB), X0
VMOVDQA X0, 0(SP)
XORQ CX, 0(SP) // 0(SP) = ·AVX_iv3 ^ (CX || 0)
- VMOVDQU 0(AX), X12
- VMOVDQU 16(AX), X15
+ VMOVDQU 0(AX), X10
+ VMOVDQU 16(AX), X11
VMOVDQU 32(AX), X2
VMOVDQU 48(AX), X3
@@ -353,124 +614,124 @@ loop:
INCQ R9
noinc:
- MOVQ R8, X8
- VPINSRQ_1_R9_X8_X8
+ VMOVQ_R8_X15
+ VPINSRQ_1_R9_X15
- VMOVDQA X12, X0
- VMOVDQA X15, X1
+ VMOVDQA X10, X0
+ VMOVDQA X11, X1
VMOVDQU ·AVX_iv0<>(SB), X4
VMOVDQU ·AVX_iv1<>(SB), X5
VMOVDQU ·AVX_iv2<>(SB), X6
- VPXOR X8, X6, X6
+ VPXOR X15, X6, X6
VMOVDQA 0(SP), X7
- LOAD_MSG_AVX(SI, 0, 2, 4, 6, 1, 3, 5, 7)
- VMOVDQA X8, 16(SP)
- VMOVDQA X9, 32(SP)
- VMOVDQA X10, 48(SP)
- VMOVDQA X11, 64(SP)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX_0_2_4_6_1_3_5_7()
+ VMOVDQA X12, 16(SP)
+ VMOVDQA X13, 32(SP)
+ VMOVDQA X14, 48(SP)
+ VMOVDQA X15, 64(SP)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
- LOAD_MSG_AVX(SI, 8, 10, 12, 14, 9, 11, 13, 15)
- VMOVDQA X8, 80(SP)
- VMOVDQA X9, 96(SP)
- VMOVDQA X10, 112(SP)
- VMOVDQA X11, 128(SP)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX(8, 10, 12, 14, 9, 11, 13, 15)
+ VMOVDQA X12, 80(SP)
+ VMOVDQA X13, 96(SP)
+ VMOVDQA X14, 112(SP)
+ VMOVDQA X15, 128(SP)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
- LOAD_MSG_AVX(SI, 14, 4, 9, 13, 10, 8, 15, 6)
- VMOVDQA X8, 144(SP)
- VMOVDQA X9, 160(SP)
- VMOVDQA X10, 176(SP)
- VMOVDQA X11, 192(SP)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX(14, 4, 9, 13, 10, 8, 15, 6)
+ VMOVDQA X12, 144(SP)
+ VMOVDQA X13, 160(SP)
+ VMOVDQA X14, 176(SP)
+ VMOVDQA X15, 192(SP)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
- LOAD_MSG_AVX(SI, 1, 0, 11, 5, 12, 2, 7, 3)
- VMOVDQA X8, 208(SP)
- VMOVDQA X9, 224(SP)
- VMOVDQA X10, 240(SP)
- VMOVDQA X11, 256(SP)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX_1_0_11_5_12_2_7_3()
+ VMOVDQA X12, 208(SP)
+ VMOVDQA X13, 224(SP)
+ VMOVDQA X14, 240(SP)
+ VMOVDQA X15, 256(SP)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
- LOAD_MSG_AVX(SI, 11, 12, 5, 15, 8, 0, 2, 13)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX_11_12_5_15_8_0_2_13()
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
- LOAD_MSG_AVX(SI, 10, 3, 7, 9, 14, 6, 1, 4)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX(10, 3, 7, 9, 14, 6, 1, 4)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
- LOAD_MSG_AVX(SI, 7, 3, 13, 11, 9, 1, 12, 14)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX(7, 3, 13, 11, 9, 1, 12, 14)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
- LOAD_MSG_AVX(SI, 2, 5, 4, 15, 6, 10, 0, 8)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX_2_5_4_15_6_10_0_8()
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
- LOAD_MSG_AVX(SI, 9, 5, 2, 10, 0, 7, 4, 15)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX_9_5_2_10_0_7_4_15()
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
- LOAD_MSG_AVX(SI, 14, 11, 6, 3, 1, 12, 8, 13)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX(14, 11, 6, 3, 1, 12, 8, 13)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
- LOAD_MSG_AVX(SI, 2, 6, 0, 8, 12, 10, 11, 3)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX_2_6_0_8_12_10_11_3()
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
- LOAD_MSG_AVX(SI, 4, 7, 15, 1, 13, 5, 14, 9)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX(4, 7, 15, 1, 13, 5, 14, 9)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
- LOAD_MSG_AVX(SI, 12, 1, 14, 4, 5, 15, 13, 10)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX(12, 1, 14, 4, 5, 15, 13, 10)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
- LOAD_MSG_AVX(SI, 0, 6, 9, 8, 7, 3, 2, 11)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX_0_6_9_8_7_3_2_11()
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
- LOAD_MSG_AVX(SI, 13, 7, 12, 3, 11, 14, 1, 9)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX(13, 7, 12, 3, 11, 14, 1, 9)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
- LOAD_MSG_AVX(SI, 5, 15, 8, 2, 0, 4, 6, 10)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX_5_15_8_2_0_4_6_10()
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
- LOAD_MSG_AVX(SI, 6, 14, 11, 0, 15, 9, 3, 8)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX_6_14_11_0_15_9_3_8()
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
- LOAD_MSG_AVX(SI, 12, 13, 1, 10, 2, 7, 4, 5)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX_12_13_1_10_2_7_4_5()
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
- LOAD_MSG_AVX(SI, 10, 8, 7, 1, 2, 4, 6, 5)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX(10, 8, 7, 1, 2, 4, 6, 5)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
- LOAD_MSG_AVX(SI, 15, 9, 3, 13, 11, 14, 12, 0)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX_15_9_3_13_11_14_12_0()
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 16(SP), 32(SP), 48(SP), 64(SP), X11, X13, X14)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 16(SP), 32(SP), 48(SP), 64(SP), X15, X8, X9)
SHUFFLE_AVX()
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 80(SP), 96(SP), 112(SP), 128(SP), X11, X13, X14)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 80(SP), 96(SP), 112(SP), 128(SP), X15, X8, X9)
SHUFFLE_AVX_INV()
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 144(SP), 160(SP), 176(SP), 192(SP), X11, X13, X14)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 144(SP), 160(SP), 176(SP), 192(SP), X15, X8, X9)
SHUFFLE_AVX()
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 208(SP), 224(SP), 240(SP), 256(SP), X11, X13, X14)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 208(SP), 224(SP), 240(SP), 256(SP), X15, X8, X9)
SHUFFLE_AVX_INV()
- VMOVDQU 32(AX), X10
- VMOVDQU 48(AX), X11
- VPXOR X0, X12, X12
- VPXOR X1, X15, X15
- VPXOR X2, X10, X10
- VPXOR X3, X11, X11
- VPXOR X4, X12, X12
- VPXOR X5, X15, X15
- VPXOR X6, X10, X2
- VPXOR X7, X11, X3
+ VMOVDQU 32(AX), X14
+ VMOVDQU 48(AX), X15
+ VPXOR X0, X10, X10
+ VPXOR X1, X11, X11
+ VPXOR X2, X14, X14
+ VPXOR X3, X15, X15
+ VPXOR X4, X10, X10
+ VPXOR X5, X11, X11
+ VPXOR X6, X14, X2
+ VPXOR X7, X15, X3
VMOVDQU X2, 32(AX)
VMOVDQU X3, 48(AX)
@@ -478,12 +739,11 @@ noinc:
SUBQ $128, DI
JNE loop
- VMOVDQU X12, 0(AX)
- VMOVDQU X15, 16(AX)
+ VMOVDQU X10, 0(AX)
+ VMOVDQU X11, 16(AX)
MOVQ R8, 0(BX)
MOVQ R9, 8(BX)
-
VZEROUPPER
MOVQ BP, SP
diff --git a/vendor/golang.org/x/crypto/blake2b/register.go b/vendor/golang.org/x/crypto/blake2b/register.go
new file mode 100644
index 0000000000..efd689af4b
--- /dev/null
+++ b/vendor/golang.org/x/crypto/blake2b/register.go
@@ -0,0 +1,32 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.9
+
+package blake2b
+
+import (
+ "crypto"
+ "hash"
+)
+
+func init() {
+ newHash256 := func() hash.Hash {
+ h, _ := New256(nil)
+ return h
+ }
+ newHash384 := func() hash.Hash {
+ h, _ := New384(nil)
+ return h
+ }
+
+ newHash512 := func() hash.Hash {
+ h, _ := New512(nil)
+ return h
+ }
+
+ crypto.RegisterHash(crypto.BLAKE2b_256, newHash256)
+ crypto.RegisterHash(crypto.BLAKE2b_384, newHash384)
+ crypto.RegisterHash(crypto.BLAKE2b_512, newHash512)
+}
diff --git a/vendor/golang.org/x/crypto/blake2s/register.go b/vendor/golang.org/x/crypto/blake2s/register.go
new file mode 100644
index 0000000000..d277459a1c
--- /dev/null
+++ b/vendor/golang.org/x/crypto/blake2s/register.go
@@ -0,0 +1,21 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.9
+
+package blake2s
+
+import (
+ "crypto"
+ "hash"
+)
+
+func init() {
+ newHash256 := func() hash.Hash {
+ h, _ := New256(nil)
+ return h
+ }
+
+ crypto.RegisterHash(crypto.BLAKE2s_256, newHash256)
+}
diff --git a/vendor/golang.org/x/crypto/cryptobyte/asn1.go b/vendor/golang.org/x/crypto/cryptobyte/asn1.go
new file mode 100644
index 0000000000..166e22d7b8
--- /dev/null
+++ b/vendor/golang.org/x/crypto/cryptobyte/asn1.go
@@ -0,0 +1,604 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package cryptobyte
+
+import (
+ "encoding/asn1"
+ "fmt"
+ "math/big"
+ "reflect"
+ "time"
+)
+
+// This file contains ASN.1-related methods for String and Builder.
+
+// Tag represents an ASN.1 tag number and class (together also referred to as
+// identifier octets). Methods in this package only support the low-tag-number
+// form, i.e. a single identifier octet with bits 7-8 encoding the class and
+// bits 1-6 encoding the tag number.
+type Tag uint8
+
+// Contructed returns t with the context-specific class bit set.
+func (t Tag) ContextSpecific() Tag { return t | 0x80 }
+
+// Contructed returns t with the constructed class bit set.
+func (t Tag) Constructed() Tag { return t | 0x20 }
+
+// Builder
+
+// AddASN1Int64 appends a DER-encoded ASN.1 INTEGER.
+func (b *Builder) AddASN1Int64(v int64) {
+ b.addASN1Signed(asn1.TagInteger, v)
+}
+
+// AddASN1Enum appends a DER-encoded ASN.1 ENUMERATION.
+func (b *Builder) AddASN1Enum(v int64) {
+ b.addASN1Signed(asn1.TagEnum, v)
+}
+
+func (b *Builder) addASN1Signed(tag Tag, v int64) {
+ b.AddASN1(tag, func(c *Builder) {
+ length := 1
+ for i := v; i >= 0x80 || i < -0x80; i >>= 8 {
+ length++
+ }
+
+ for ; length > 0; length-- {
+ i := v >> uint((length-1)*8) & 0xff
+ c.AddUint8(uint8(i))
+ }
+ })
+}
+
+// AddASN1Uint64 appends a DER-encoded ASN.1 INTEGER.
+func (b *Builder) AddASN1Uint64(v uint64) {
+ b.AddASN1(asn1.TagInteger, func(c *Builder) {
+ length := 1
+ for i := v; i >= 0x80; i >>= 8 {
+ length++
+ }
+
+ for ; length > 0; length-- {
+ i := v >> uint((length-1)*8) & 0xff
+ c.AddUint8(uint8(i))
+ }
+ })
+}
+
+// AddASN1BigInt appends a DER-encoded ASN.1 INTEGER.
+func (b *Builder) AddASN1BigInt(n *big.Int) {
+ if b.err != nil {
+ return
+ }
+
+ b.AddASN1(asn1.TagInteger, func(c *Builder) {
+ if n.Sign() < 0 {
+ // A negative number has to be converted to two's-complement form. So we
+ // 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)
+ nMinus1.Sub(nMinus1, bigOne)
+ bytes := nMinus1.Bytes()
+ for i := range bytes {
+ bytes[i] ^= 0xff
+ }
+ if bytes[0]&0x80 == 0 {
+ c.add(0xff)
+ }
+ c.add(bytes...)
+ } else if n.Sign() == 0 {
+ c.add(0)
+ } else {
+ bytes := n.Bytes()
+ if bytes[0]&0x80 != 0 {
+ c.add(0)
+ }
+ c.add(bytes...)
+ }
+ })
+}
+
+// AddASN1OctetString appends a DER-encoded ASN.1 OCTET STRING.
+func (b *Builder) AddASN1OctetString(bytes []byte) {
+ b.AddASN1(asn1.TagOctetString, func(c *Builder) {
+ c.AddBytes(bytes)
+ })
+}
+
+const generalizedTimeFormatStr = "20060102150405Z0700"
+
+// AddASN1GeneralizedTime appends a DER-encoded ASN.1 GENERALIZEDTIME.
+func (b *Builder) AddASN1GeneralizedTime(t time.Time) {
+ if t.Year() < 0 || t.Year() > 9999 {
+ b.err = fmt.Errorf("cryptobyte: cannot represent %v as a GeneralizedTime", t)
+ return
+ }
+ b.AddASN1(asn1.TagGeneralizedTime, func(c *Builder) {
+ c.AddBytes([]byte(t.Format(generalizedTimeFormatStr)))
+ })
+}
+
+// AddASN1BitString appends a DER-encoded ASN.1 BIT STRING.
+func (b *Builder) AddASN1BitString(s asn1.BitString) {
+ // TODO(martinkr): Implement.
+ b.MarshalASN1(s)
+}
+
+// MarshalASN1 calls asn1.Marshal on its input and appends the result if
+// successful or records an error if one occurred.
+func (b *Builder) MarshalASN1(v interface{}) {
+ // NOTE(martinkr): This is somewhat of a hack to allow propagation of
+ // asn1.Marshal errors into Builder.err. N.B. if you call MarshalASN1 with a
+ // value embedded into a struct, its tag information is lost.
+ if b.err != nil {
+ return
+ }
+ bytes, err := asn1.Marshal(v)
+ if err != nil {
+ b.err = err
+ return
+ }
+ b.AddBytes(bytes)
+}
+
+// AddASN1 appends an ASN.1 object. The object is prefixed with the given tag.
+// Tags greater than 30 are not supported and result in an error (i.e.
+// low-tag-number form only). The child builder passed to the
+// BuilderContinuation can be used to build the content of the ASN.1 object.
+func (b *Builder) AddASN1(tag Tag, f BuilderContinuation) {
+ if b.err != nil {
+ return
+ }
+ // Identifiers with the low five bits set indicate high-tag-number format
+ // (two or more octets), which we don't support.
+ if tag&0x1f == 0x1f {
+ b.err = fmt.Errorf("cryptobyte: high-tag number identifier octects not supported: 0x%x", tag)
+ return
+ }
+ b.AddUint8(uint8(tag))
+ b.addLengthPrefixed(1, true, f)
+}
+
+// String
+
+var bigIntType = reflect.TypeOf((*big.Int)(nil)).Elem()
+
+// ReadASN1Integer decodes an ASN.1 INTEGER into out and advances. If out does
+// not point to an integer or to a big.Int, it panics. It returns true on
+// success and false on error.
+func (s *String) ReadASN1Integer(out interface{}) bool {
+ if reflect.TypeOf(out).Kind() != reflect.Ptr {
+ panic("out is not a pointer")
+ }
+ switch reflect.ValueOf(out).Elem().Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ var i int64
+ if !s.readASN1Int64(&i) || reflect.ValueOf(out).Elem().OverflowInt(i) {
+ return false
+ }
+ reflect.ValueOf(out).Elem().SetInt(i)
+ return true
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ var u uint64
+ if !s.readASN1Uint64(&u) || reflect.ValueOf(out).Elem().OverflowUint(u) {
+ return false
+ }
+ reflect.ValueOf(out).Elem().SetUint(u)
+ return true
+ case reflect.Struct:
+ if reflect.TypeOf(out).Elem() == bigIntType {
+ return s.readASN1BigInt(out.(*big.Int))
+ }
+ }
+ panic("out does not point to an integer type")
+}
+
+func checkASN1Integer(bytes []byte) bool {
+ if len(bytes) == 0 {
+ // An INTEGER is encoded with at least one octet.
+ return false
+ }
+ if len(bytes) == 1 {
+ return true
+ }
+ if bytes[0] == 0 && bytes[1]&0x80 == 0 || bytes[0] == 0xff && bytes[1]&0x80 == 0x80 {
+ // Value is not minimally encoded.
+ return false
+ }
+ return true
+}
+
+var bigOne = big.NewInt(1)
+
+func (s *String) readASN1BigInt(out *big.Int) bool {
+ var bytes String
+ if !s.ReadASN1(&bytes, asn1.TagInteger) || !checkASN1Integer(bytes) {
+ return false
+ }
+ if bytes[0]&0x80 == 0x80 {
+ // Negative number.
+ neg := make([]byte, len(bytes))
+ for i, b := range bytes {
+ neg[i] = ^b
+ }
+ out.SetBytes(neg)
+ out.Add(out, bigOne)
+ out.Neg(out)
+ } else {
+ out.SetBytes(bytes)
+ }
+ return true
+}
+
+func (s *String) readASN1Int64(out *int64) bool {
+ var bytes String
+ if !s.ReadASN1(&bytes, asn1.TagInteger) || !checkASN1Integer(bytes) || !asn1Signed(out, bytes) {
+ return false
+ }
+ return true
+}
+
+func asn1Signed(out *int64, n []byte) bool {
+ length := len(n)
+ if length > 8 {
+ return false
+ }
+ for i := 0; i < length; i++ {
+ *out <<= 8
+ *out |= int64(n[i])
+ }
+ // Shift up and down in order to sign extend the result.
+ *out <<= 64 - uint8(length)*8
+ *out >>= 64 - uint8(length)*8
+ return true
+}
+
+func (s *String) readASN1Uint64(out *uint64) bool {
+ var bytes String
+ if !s.ReadASN1(&bytes, asn1.TagInteger) || !checkASN1Integer(bytes) || !asn1Unsigned(out, bytes) {
+ return false
+ }
+ return true
+}
+
+func asn1Unsigned(out *uint64, n []byte) bool {
+ length := len(n)
+ if length > 9 || length == 9 && n[0] != 0 {
+ // Too large for uint64.
+ return false
+ }
+ if n[0]&0x80 != 0 {
+ // Negative number.
+ return false
+ }
+ for i := 0; i < length; i++ {
+ *out <<= 8
+ *out |= uint64(n[i])
+ }
+ return true
+}
+
+// ReadASN1Enum decodes an ASN.1 ENUMERATION into out and advances. It returns
+// true on success and false on error.
+func (s *String) ReadASN1Enum(out *int) bool {
+ var bytes String
+ var i int64
+ if !s.ReadASN1(&bytes, asn1.TagEnum) || !checkASN1Integer(bytes) || !asn1Signed(&i, bytes) {
+ return false
+ }
+ if int64(int(i)) != i {
+ return false
+ }
+ *out = int(i)
+ return true
+}
+
+func (s *String) readBase128Int(out *int) bool {
+ ret := 0
+ for i := 0; len(*s) > 0; i++ {
+ if i == 4 {
+ return false
+ }
+ ret <<= 7
+ b := s.read(1)[0]
+ ret |= int(b & 0x7f)
+ if b&0x80 == 0 {
+ *out = ret
+ return true
+ }
+ }
+ return false // truncated
+}
+
+// ReadASN1ObjectIdentifier decodes an ASN.1 OBJECT IDENTIFIER into out and
+// advances. It returns true on success and false on error.
+func (s *String) ReadASN1ObjectIdentifier(out *asn1.ObjectIdentifier) bool {
+ var bytes String
+ if !s.ReadASN1(&bytes, asn1.TagOID) || len(bytes) == 0 {
+ return false
+ }
+
+ // In the worst case, we get two elements from the first byte (which is
+ // encoded differently) and then every varint is a single byte long.
+ components := make([]int, len(bytes)+1)
+
+ // The first varint is 40*value1 + value2:
+ // According to this packing, value1 can take the values 0, 1 and 2 only.
+ // When value1 = 0 or value1 = 1, then value2 is <= 39. When value1 = 2,
+ // then there are no restrictions on value2.
+ var v int
+ if !bytes.readBase128Int(&v) {
+ return false
+ }
+ if v < 80 {
+ components[0] = v / 40
+ components[1] = v % 40
+ } else {
+ components[0] = 2
+ components[1] = v - 80
+ }
+
+ i := 2
+ for ; len(bytes) > 0; i++ {
+ if !bytes.readBase128Int(&v) {
+ return false
+ }
+ components[i] = v
+ }
+ *out = components[:i]
+ return true
+}
+
+// ReadASN1GeneralizedTime decodes an ASN.1 GENERALIZEDTIME into out and
+// advances. It returns true on success and false on error.
+func (s *String) ReadASN1GeneralizedTime(out *time.Time) bool {
+ var bytes String
+ if !s.ReadASN1(&bytes, asn1.TagGeneralizedTime) {
+ return false
+ }
+ t := string(bytes)
+ res, err := time.Parse(generalizedTimeFormatStr, t)
+ if err != nil {
+ return false
+ }
+ if serialized := res.Format(generalizedTimeFormatStr); serialized != t {
+ return false
+ }
+ *out = res
+ return true
+}
+
+// ReadASN1BitString decodes an ASN.1 BIT STRING into out and advances. It
+// returns true on success and false on error.
+func (s *String) ReadASN1BitString(out *asn1.BitString) bool {
+ var bytes String
+ if !s.ReadASN1(&bytes, asn1.TagBitString) || len(bytes) == 0 {
+ return false
+ }
+
+ paddingBits := uint8(bytes[0])
+ bytes = bytes[1:]
+ if paddingBits > 7 ||
+ len(bytes) == 0 && paddingBits != 0 ||
+ len(bytes) > 0 && bytes[len(bytes)-1]&(1< 4 || len(*s) < int(2+lenLen) {
+ return false
+ }
+
+ lenBytes := String((*s)[2 : 2+lenLen])
+ if !lenBytes.readUnsigned(&len32, int(lenLen)) {
+ return false
+ }
+
+ // ITU-T X.690 section 10.1 (DER length forms) requires encoding the length
+ // with the minimum number of octets.
+ if len32 < 128 {
+ // Length should have used short-form encoding.
+ return false
+ }
+ if len32>>((lenLen-1)*8) == 0 {
+ // Leading octet is 0. Length should have been at least one byte shorter.
+ return false
+ }
+
+ headerLen = 2 + uint32(lenLen)
+ if headerLen+len32 < len32 {
+ // Overflow.
+ return false
+ }
+ length = headerLen + len32
+ }
+
+ if uint32(int(length)) != length || !s.ReadBytes((*[]byte)(out), int(length)) {
+ return false
+ }
+ if skipHeader && !out.Skip(int(headerLen)) {
+ panic("cryptobyte: internal error")
+ }
+
+ return true
+}
diff --git a/vendor/golang.org/x/crypto/cryptobyte/asn1_test.go b/vendor/golang.org/x/crypto/cryptobyte/asn1_test.go
new file mode 100644
index 0000000000..c8c1870323
--- /dev/null
+++ b/vendor/golang.org/x/crypto/cryptobyte/asn1_test.go
@@ -0,0 +1,285 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package cryptobyte
+
+import (
+ "bytes"
+ "encoding/asn1"
+ "math/big"
+ "reflect"
+ "testing"
+ "time"
+)
+
+type readASN1Test struct {
+ name string
+ in []byte
+ tag Tag
+ ok bool
+ out interface{}
+}
+
+var readASN1TestData = []readASN1Test{
+ {"valid", []byte{0x30, 2, 1, 2}, 0x30, true, []byte{1, 2}},
+ {"truncated", []byte{0x30, 3, 1, 2}, 0x30, false, nil},
+ {"zero length of length", []byte{0x30, 0x80}, 0x30, false, nil},
+ {"invalid long form length", []byte{0x30, 0x81, 1, 1}, 0x30, false, nil},
+ {"non-minimal length", append([]byte{0x30, 0x82, 0, 0x80}, make([]byte, 0x80)...), 0x30, false, nil},
+ {"invalid tag", []byte{0xa1, 3, 0x4, 1, 1}, 31, false, nil},
+ {"high tag", []byte{0x1f, 0x81, 0x80, 0x01, 2, 1, 2}, 0xff /* actually 0x4001, but tag is uint8 */, false, nil},
+}
+
+func TestReadASN1(t *testing.T) {
+ for _, test := range readASN1TestData {
+ t.Run(test.name, func(t *testing.T) {
+ var in, out String = test.in, nil
+ ok := in.ReadASN1(&out, test.tag)
+ if ok != test.ok || ok && !bytes.Equal(out, test.out.([]byte)) {
+ t.Errorf("in.ReadASN1() = %v, want %v; out = %v, want %v", ok, test.ok, out, test.out)
+ }
+ })
+ }
+}
+
+func TestReadASN1Optional(t *testing.T) {
+ var empty String
+ var present bool
+ ok := empty.ReadOptionalASN1(nil, &present, 0xa0)
+ if !ok || present {
+ t.Errorf("empty.ReadOptionalASN1() = %v, want true; present = %v want false", ok, present)
+ }
+
+ var in, out String = []byte{0xa1, 3, 0x4, 1, 1}, nil
+ ok = in.ReadOptionalASN1(&out, &present, 0xa0)
+ if !ok || present {
+ t.Errorf("in.ReadOptionalASN1() = %v, want true, present = %v, want false", ok, present)
+ }
+ ok = in.ReadOptionalASN1(&out, &present, 0xa1)
+ wantBytes := []byte{4, 1, 1}
+ if !ok || !present || !bytes.Equal(out, wantBytes) {
+ t.Errorf("in.ReadOptionalASN1() = %v, want true; present = %v, want true; out = %v, want = %v", ok, present, out, wantBytes)
+ }
+}
+
+var optionalOctetStringTestData = []struct {
+ readASN1Test
+ present bool
+}{
+ {readASN1Test{"empty", []byte{}, 0xa0, true, []byte{}}, false},
+ {readASN1Test{"invalid", []byte{0xa1, 3, 0x4, 2, 1}, 0xa1, false, []byte{}}, true},
+ {readASN1Test{"missing", []byte{0xa1, 3, 0x4, 1, 1}, 0xa0, true, []byte{}}, false},
+ {readASN1Test{"present", []byte{0xa1, 3, 0x4, 1, 1}, 0xa1, true, []byte{1}}, true},
+}
+
+func TestReadASN1OptionalOctetString(t *testing.T) {
+ for _, test := range optionalOctetStringTestData {
+ t.Run(test.name, func(t *testing.T) {
+ in := String(test.in)
+ var out []byte
+ var present bool
+ ok := in.ReadOptionalASN1OctetString(&out, &present, test.tag)
+ if ok != test.ok || present != test.present || !bytes.Equal(out, test.out.([]byte)) {
+ t.Errorf("in.ReadOptionalASN1OctetString() = %v, want %v; present = %v want %v; out = %v, want %v", ok, test.ok, present, test.present, out, test.out)
+ }
+ })
+ }
+}
+
+const defaultInt = -1
+
+var optionalIntTestData = []readASN1Test{
+ {"empty", []byte{}, 0xa0, true, defaultInt},
+ {"invalid", []byte{0xa1, 3, 0x2, 2, 127}, 0xa1, false, 0},
+ {"missing", []byte{0xa1, 3, 0x2, 1, 127}, 0xa0, true, defaultInt},
+ {"present", []byte{0xa1, 3, 0x2, 1, 42}, 0xa1, true, 42},
+}
+
+func TestReadASN1OptionalInteger(t *testing.T) {
+ for _, test := range optionalIntTestData {
+ t.Run(test.name, func(t *testing.T) {
+ in := String(test.in)
+ var out int
+ ok := in.ReadOptionalASN1Integer(&out, test.tag, defaultInt)
+ if ok != test.ok || ok && out != test.out.(int) {
+ t.Errorf("in.ReadOptionalASN1Integer() = %v, want %v; out = %v, want %v", ok, test.ok, out, test.out)
+ }
+ })
+ }
+}
+
+func TestReadASN1IntegerSigned(t *testing.T) {
+ testData64 := []struct {
+ in []byte
+ out int64
+ }{
+ {[]byte{2, 3, 128, 0, 0}, -0x800000},
+ {[]byte{2, 2, 255, 0}, -256},
+ {[]byte{2, 2, 255, 127}, -129},
+ {[]byte{2, 1, 128}, -128},
+ {[]byte{2, 1, 255}, -1},
+ {[]byte{2, 1, 0}, 0},
+ {[]byte{2, 1, 1}, 1},
+ {[]byte{2, 1, 2}, 2},
+ {[]byte{2, 1, 127}, 127},
+ {[]byte{2, 2, 0, 128}, 128},
+ {[]byte{2, 2, 1, 0}, 256},
+ {[]byte{2, 4, 0, 128, 0, 0}, 0x800000},
+ }
+ for i, test := range testData64 {
+ in := String(test.in)
+ var out int64
+ ok := in.ReadASN1Integer(&out)
+ if !ok || out != test.out {
+ t.Errorf("#%d: in.ReadASN1Integer() = %v, want true; out = %d, want %d", i, ok, out, test.out)
+ }
+ }
+
+ // Repeat the same cases, reading into a big.Int.
+ t.Run("big.Int", func(t *testing.T) {
+ for i, test := range testData64 {
+ in := String(test.in)
+ var out big.Int
+ ok := in.ReadASN1Integer(&out)
+ if !ok || out.Int64() != test.out {
+ t.Errorf("#%d: in.ReadASN1Integer() = %v, want true; out = %d, want %d", i, ok, out.Int64(), test.out)
+ }
+ }
+ })
+}
+
+func TestReadASN1IntegerUnsigned(t *testing.T) {
+ testData := []struct {
+ in []byte
+ out uint64
+ }{
+ {[]byte{2, 1, 0}, 0},
+ {[]byte{2, 1, 1}, 1},
+ {[]byte{2, 1, 2}, 2},
+ {[]byte{2, 1, 127}, 127},
+ {[]byte{2, 2, 0, 128}, 128},
+ {[]byte{2, 2, 1, 0}, 256},
+ {[]byte{2, 4, 0, 128, 0, 0}, 0x800000},
+ {[]byte{2, 8, 127, 255, 255, 255, 255, 255, 255, 255}, 0x7fffffffffffffff},
+ {[]byte{2, 9, 0, 128, 0, 0, 0, 0, 0, 0, 0}, 0x8000000000000000},
+ {[]byte{2, 9, 0, 255, 255, 255, 255, 255, 255, 255, 255}, 0xffffffffffffffff},
+ }
+ for i, test := range testData {
+ in := String(test.in)
+ var out uint64
+ ok := in.ReadASN1Integer(&out)
+ if !ok || out != test.out {
+ t.Errorf("#%d: in.ReadASN1Integer() = %v, want true; out = %d, want %d", i, ok, out, test.out)
+ }
+ }
+}
+
+func TestReadASN1IntegerInvalid(t *testing.T) {
+ testData := []String{
+ []byte{3, 1, 0}, // invalid tag
+ // truncated
+ []byte{2, 1},
+ []byte{2, 2, 0},
+ // not minimally encoded
+ []byte{2, 2, 0, 1},
+ []byte{2, 2, 0xff, 0xff},
+ }
+
+ for i, test := range testData {
+ var out int64
+ if test.ReadASN1Integer(&out) {
+ t.Errorf("#%d: in.ReadASN1Integer() = true, want false (out = %d)", i, out)
+ }
+ }
+}
+
+func TestReadASN1ObjectIdentifier(t *testing.T) {
+ testData := []struct {
+ in []byte
+ ok bool
+ out []int
+ }{
+ {[]byte{}, false, []int{}},
+ {[]byte{6, 0}, false, []int{}},
+ {[]byte{5, 1, 85}, false, []int{2, 5}},
+ {[]byte{6, 1, 85}, true, []int{2, 5}},
+ {[]byte{6, 2, 85, 0x02}, true, []int{2, 5, 2}},
+ {[]byte{6, 4, 85, 0x02, 0xc0, 0x00}, true, []int{2, 5, 2, 0x2000}},
+ {[]byte{6, 3, 0x81, 0x34, 0x03}, true, []int{2, 100, 3}},
+ {[]byte{6, 7, 85, 0x02, 0xc0, 0x80, 0x80, 0x80, 0x80}, false, []int{}},
+ }
+
+ for i, test := range testData {
+ in := String(test.in)
+ var out asn1.ObjectIdentifier
+ ok := in.ReadASN1ObjectIdentifier(&out)
+ if ok != test.ok || ok && !out.Equal(test.out) {
+ t.Errorf("#%d: in.ReadASN1ObjectIdentifier() = %v, want %v; out = %v, want %v", i, ok, test.ok, out, test.out)
+ }
+ }
+}
+
+func TestReadASN1GeneralizedTime(t *testing.T) {
+ testData := []struct {
+ in string
+ ok bool
+ out time.Time
+ }{
+ {"20100102030405Z", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.UTC)},
+ {"20100102030405", false, time.Time{}},
+ {"20100102030405+0607", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.FixedZone("", 6*60*60+7*60))},
+ {"20100102030405-0607", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.FixedZone("", -6*60*60-7*60))},
+ /* These are invalid times. However, the time package normalises times
+ * and they were accepted in some versions. See #11134. */
+ {"00000100000000Z", false, time.Time{}},
+ {"20101302030405Z", false, time.Time{}},
+ {"20100002030405Z", false, time.Time{}},
+ {"20100100030405Z", false, time.Time{}},
+ {"20100132030405Z", false, time.Time{}},
+ {"20100231030405Z", false, time.Time{}},
+ {"20100102240405Z", false, time.Time{}},
+ {"20100102036005Z", false, time.Time{}},
+ {"20100102030460Z", false, time.Time{}},
+ {"-20100102030410Z", false, time.Time{}},
+ {"2010-0102030410Z", false, time.Time{}},
+ {"2010-0002030410Z", false, time.Time{}},
+ {"201001-02030410Z", false, time.Time{}},
+ {"20100102-030410Z", false, time.Time{}},
+ {"2010010203-0410Z", false, time.Time{}},
+ {"201001020304-10Z", false, time.Time{}},
+ }
+ for i, test := range testData {
+ in := String(append([]byte{asn1.TagGeneralizedTime, byte(len(test.in))}, test.in...))
+ var out time.Time
+ ok := in.ReadASN1GeneralizedTime(&out)
+ if ok != test.ok || ok && !reflect.DeepEqual(out, test.out) {
+ t.Errorf("#%d: in.ReadASN1GeneralizedTime() = %v, want %v; out = %q, want %q", i, ok, test.ok, out, test.out)
+ }
+ }
+}
+
+func TestReadASN1BitString(t *testing.T) {
+ testData := []struct {
+ in []byte
+ ok bool
+ out asn1.BitString
+ }{
+ {[]byte{}, false, asn1.BitString{}},
+ {[]byte{0x00}, true, asn1.BitString{}},
+ {[]byte{0x07, 0x00}, true, asn1.BitString{Bytes: []byte{0}, BitLength: 1}},
+ {[]byte{0x07, 0x01}, false, asn1.BitString{}},
+ {[]byte{0x07, 0x40}, false, asn1.BitString{}},
+ {[]byte{0x08, 0x00}, false, asn1.BitString{}},
+ {[]byte{0xff}, false, asn1.BitString{}},
+ {[]byte{0xfe, 0x00}, false, asn1.BitString{}},
+ }
+ for i, test := range testData {
+ in := String(append([]byte{3, byte(len(test.in))}, test.in...))
+ var out asn1.BitString
+ ok := in.ReadASN1BitString(&out)
+ if ok != test.ok || ok && (!bytes.Equal(out.Bytes, test.out.Bytes) || out.BitLength != test.out.BitLength) {
+ t.Errorf("#%d: in.ReadASN1BitString() = %v, want %v; out = %v, want %v", i, ok, test.ok, out, test.out)
+ }
+ }
+}
diff --git a/vendor/golang.org/x/crypto/cryptobyte/builder.go b/vendor/golang.org/x/crypto/cryptobyte/builder.go
new file mode 100644
index 0000000000..9883fb3c39
--- /dev/null
+++ b/vendor/golang.org/x/crypto/cryptobyte/builder.go
@@ -0,0 +1,255 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package cryptobyte
+
+import (
+ "errors"
+ "fmt"
+)
+
+// A Builder builds byte strings from fixed-length and length-prefixed values.
+// The zero value is a usable Builder that allocates space as needed.
+type Builder struct {
+ err error
+ result []byte
+ fixedSize bool
+ child *Builder
+ offset int
+ pendingLenLen int
+ pendingIsASN1 bool
+}
+
+// NewBuilder creates a Builder that appends its output to the given buffer.
+// Like append(), the slice will be reallocated if its capacity is exceeded.
+// Use Bytes to get the final buffer.
+func NewBuilder(buffer []byte) *Builder {
+ return &Builder{
+ result: buffer,
+ }
+}
+
+// NewFixedBuilder creates a Builder that appends its output into the given
+// buffer. This builder does not reallocate the output buffer. Writes that
+// would exceed the buffer's capacity are treated as an error.
+func NewFixedBuilder(buffer []byte) *Builder {
+ return &Builder{
+ result: buffer,
+ fixedSize: true,
+ }
+}
+
+// Bytes returns the bytes written by the builder or an error if one has
+// occurred during during building.
+func (b *Builder) Bytes() ([]byte, error) {
+ if b.err != nil {
+ return nil, b.err
+ }
+ return b.result[b.offset:], nil
+}
+
+// BytesOrPanic returns the bytes written by the builder or panics if an error
+// has occurred during building.
+func (b *Builder) BytesOrPanic() []byte {
+ if b.err != nil {
+ panic(b.err)
+ }
+ return b.result[b.offset:]
+}
+
+// AddUint8 appends an 8-bit value to the byte string.
+func (b *Builder) AddUint8(v uint8) {
+ b.add(byte(v))
+}
+
+// AddUint16 appends a big-endian, 16-bit value to the byte string.
+func (b *Builder) AddUint16(v uint16) {
+ b.add(byte(v>>8), byte(v))
+}
+
+// AddUint24 appends a big-endian, 24-bit value to the byte string. The highest
+// byte of the 32-bit input value is silently truncated.
+func (b *Builder) AddUint24(v uint32) {
+ b.add(byte(v>>16), byte(v>>8), byte(v))
+}
+
+// AddUint32 appends a big-endian, 32-bit value to the byte string.
+func (b *Builder) AddUint32(v uint32) {
+ b.add(byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
+}
+
+// AddBytes appends a sequence of bytes to the byte string.
+func (b *Builder) AddBytes(v []byte) {
+ b.add(v...)
+}
+
+// BuilderContinuation is continuation-passing interface for building
+// length-prefixed byte sequences. Builder methods for length-prefixed
+// sequences (AddUint8LengthPrefixed etc.) will invoke the BuilderContinuation
+// supplied to them. The child builder passed to the continuation can be used
+// to build the content of the length-prefixed sequence. Example:
+//
+// parent := cryptobyte.NewBuilder()
+// parent.AddUint8LengthPrefixed(func (child *Builder) {
+// child.AddUint8(42)
+// child.AddUint8LengthPrefixed(func (grandchild *Builder) {
+// grandchild.AddUint8(5)
+// })
+// })
+//
+// It is an error to write more bytes to the child than allowed by the reserved
+// length prefix. After the continuation returns, the child must be considered
+// invalid, i.e. users must not store any copies or references of the child
+// that outlive the continuation.
+type BuilderContinuation func(child *Builder)
+
+// AddUint8LengthPrefixed adds a 8-bit length-prefixed byte sequence.
+func (b *Builder) AddUint8LengthPrefixed(f BuilderContinuation) {
+ b.addLengthPrefixed(1, false, f)
+}
+
+// AddUint16LengthPrefixed adds a big-endian, 16-bit length-prefixed byte sequence.
+func (b *Builder) AddUint16LengthPrefixed(f BuilderContinuation) {
+ b.addLengthPrefixed(2, false, f)
+}
+
+// AddUint24LengthPrefixed adds a big-endian, 24-bit length-prefixed byte sequence.
+func (b *Builder) AddUint24LengthPrefixed(f BuilderContinuation) {
+ b.addLengthPrefixed(3, false, f)
+}
+
+func (b *Builder) addLengthPrefixed(lenLen int, isASN1 bool, f BuilderContinuation) {
+ // Subsequent writes can be ignored if the builder has encountered an error.
+ if b.err != nil {
+ return
+ }
+
+ offset := len(b.result)
+ b.add(make([]byte, lenLen)...)
+
+ b.child = &Builder{
+ result: b.result,
+ fixedSize: b.fixedSize,
+ offset: offset,
+ pendingLenLen: lenLen,
+ pendingIsASN1: isASN1,
+ }
+
+ f(b.child)
+ b.flushChild()
+ if b.child != nil {
+ panic("cryptobyte: internal error")
+ }
+}
+
+func (b *Builder) flushChild() {
+ if b.child == nil {
+ return
+ }
+ b.child.flushChild()
+ child := b.child
+ b.child = nil
+
+ if child.err != nil {
+ b.err = child.err
+ return
+ }
+
+ length := len(child.result) - child.pendingLenLen - child.offset
+
+ if length < 0 {
+ panic("cryptobyte: internal error") // result unexpectedly shrunk
+ }
+
+ if child.pendingIsASN1 {
+ // For ASN.1, we reserved a single byte for the length. If that turned out
+ // to be incorrect, we have to move the contents along in order to make
+ // space.
+ if child.pendingLenLen != 1 {
+ panic("cryptobyte: internal error")
+ }
+ var lenLen, lenByte uint8
+ if int64(length) > 0xfffffffe {
+ b.err = errors.New("pending ASN.1 child too long")
+ return
+ } else if length > 0xffffff {
+ lenLen = 5
+ lenByte = 0x80 | 4
+ } else if length > 0xffff {
+ lenLen = 4
+ lenByte = 0x80 | 3
+ } else if length > 0xff {
+ lenLen = 3
+ lenByte = 0x80 | 2
+ } else if length > 0x7f {
+ lenLen = 2
+ lenByte = 0x80 | 1
+ } else {
+ lenLen = 1
+ lenByte = uint8(length)
+ length = 0
+ }
+
+ // Insert the initial length byte, make space for successive length bytes,
+ // and adjust the offset.
+ child.result[child.offset] = lenByte
+ extraBytes := int(lenLen - 1)
+ if extraBytes != 0 {
+ child.add(make([]byte, extraBytes)...)
+ childStart := child.offset + child.pendingLenLen
+ copy(child.result[childStart+extraBytes:], child.result[childStart:])
+ }
+ child.offset++
+ child.pendingLenLen = extraBytes
+ }
+
+ l := length
+ for i := child.pendingLenLen - 1; i >= 0; i-- {
+ child.result[child.offset+i] = uint8(l)
+ l >>= 8
+ }
+ if l != 0 {
+ b.err = fmt.Errorf("cryptobyte: pending child length %d exceeds %d-byte length prefix", length, child.pendingLenLen)
+ return
+ }
+
+ if !b.fixedSize {
+ b.result = child.result // In case child reallocated result.
+ }
+}
+
+func (b *Builder) add(bytes ...byte) {
+ if b.err != nil {
+ return
+ }
+ if b.child != nil {
+ panic("attempted write while child is pending")
+ }
+ if len(b.result)+len(bytes) < len(bytes) {
+ b.err = errors.New("cryptobyte: length overflow")
+ }
+ if b.fixedSize && len(b.result)+len(bytes) > cap(b.result) {
+ b.err = errors.New("cryptobyte: Builder is exceeding its fixed-size buffer")
+ return
+ }
+ b.result = append(b.result, bytes...)
+}
+
+// A MarshalingValue marshals itself into a Builder.
+type MarshalingValue interface {
+ // Marshal is called by Builder.AddValue. It receives a pointer to a builder
+ // to marshal itself into. It may return an error that occurred during
+ // marshaling, such as unset or invalid values.
+ Marshal(b *Builder) error
+}
+
+// AddValue calls Marshal on v, passing a pointer to the builder to append to.
+// If Marshal returns an error, it is set on the Builder so that subsequent
+// appends don't have an effect.
+func (b *Builder) AddValue(v MarshalingValue) {
+ err := v.Marshal(b)
+ if err != nil {
+ b.err = err
+ }
+}
diff --git a/vendor/golang.org/x/crypto/cryptobyte/cryptobyte_test.go b/vendor/golang.org/x/crypto/cryptobyte/cryptobyte_test.go
new file mode 100644
index 0000000000..49c61dca4a
--- /dev/null
+++ b/vendor/golang.org/x/crypto/cryptobyte/cryptobyte_test.go
@@ -0,0 +1,379 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package cryptobyte
+
+import (
+ "bytes"
+ "fmt"
+ "testing"
+)
+
+func builderBytesEq(b *Builder, want ...byte) error {
+ got := b.BytesOrPanic()
+ if !bytes.Equal(got, want) {
+ return fmt.Errorf("Bytes() = %v, want %v", got, want)
+ }
+ return nil
+}
+
+func TestBytes(t *testing.T) {
+ var b Builder
+ v := []byte("foobarbaz")
+ b.AddBytes(v[0:3])
+ b.AddBytes(v[3:4])
+ b.AddBytes(v[4:9])
+ if err := builderBytesEq(&b, v...); err != nil {
+ t.Error(err)
+ }
+ s := String(b.BytesOrPanic())
+ for _, w := range []string{"foo", "bar", "baz"} {
+ var got []byte
+ if !s.ReadBytes(&got, 3) {
+ t.Errorf("ReadBytes() = false, want true (w = %v)", w)
+ }
+ want := []byte(w)
+ if !bytes.Equal(got, want) {
+ t.Errorf("ReadBytes(): got = %v, want %v", got, want)
+ }
+ }
+ if len(s) != 0 {
+ t.Errorf("len(s) = %d, want 0", len(s))
+ }
+}
+
+func TestUint8(t *testing.T) {
+ var b Builder
+ b.AddUint8(42)
+ if err := builderBytesEq(&b, 42); err != nil {
+ t.Error(err)
+ }
+
+ var s String = b.BytesOrPanic()
+ var v uint8
+ if !s.ReadUint8(&v) {
+ t.Error("ReadUint8() = false, want true")
+ }
+ if v != 42 {
+ t.Errorf("v = %d, want 42", v)
+ }
+ if len(s) != 0 {
+ t.Errorf("len(s) = %d, want 0", len(s))
+ }
+}
+
+func TestUint16(t *testing.T) {
+ var b Builder
+ b.AddUint16(65534)
+ if err := builderBytesEq(&b, 255, 254); err != nil {
+ t.Error(err)
+ }
+ var s String = b.BytesOrPanic()
+ var v uint16
+ if !s.ReadUint16(&v) {
+ t.Error("ReadUint16() == false, want true")
+ }
+ if v != 65534 {
+ t.Errorf("v = %d, want 65534", v)
+ }
+ if len(s) != 0 {
+ t.Errorf("len(s) = %d, want 0", len(s))
+ }
+}
+
+func TestUint24(t *testing.T) {
+ var b Builder
+ b.AddUint24(0xfffefd)
+ if err := builderBytesEq(&b, 255, 254, 253); err != nil {
+ t.Error(err)
+ }
+
+ var s String = b.BytesOrPanic()
+ var v uint32
+ if !s.ReadUint24(&v) {
+ t.Error("ReadUint8() = false, want true")
+ }
+ if v != 0xfffefd {
+ t.Errorf("v = %d, want fffefd", v)
+ }
+ if len(s) != 0 {
+ t.Errorf("len(s) = %d, want 0", len(s))
+ }
+}
+
+func TestUint24Truncation(t *testing.T) {
+ var b Builder
+ b.AddUint24(0x10111213)
+ if err := builderBytesEq(&b, 0x11, 0x12, 0x13); err != nil {
+ t.Error(err)
+ }
+}
+
+func TestUint32(t *testing.T) {
+ var b Builder
+ b.AddUint32(0xfffefdfc)
+ if err := builderBytesEq(&b, 255, 254, 253, 252); err != nil {
+ t.Error(err)
+ }
+
+ var s String = b.BytesOrPanic()
+ var v uint32
+ if !s.ReadUint32(&v) {
+ t.Error("ReadUint8() = false, want true")
+ }
+ if v != 0xfffefdfc {
+ t.Errorf("v = %x, want fffefdfc", v)
+ }
+ if len(s) != 0 {
+ t.Errorf("len(s) = %d, want 0", len(s))
+ }
+}
+
+func TestUMultiple(t *testing.T) {
+ var b Builder
+ b.AddUint8(23)
+ b.AddUint32(0xfffefdfc)
+ b.AddUint16(42)
+ if err := builderBytesEq(&b, 23, 255, 254, 253, 252, 0, 42); err != nil {
+ t.Error(err)
+ }
+
+ var s String = b.BytesOrPanic()
+ var (
+ x uint8
+ y uint32
+ z uint16
+ )
+ if !s.ReadUint8(&x) || !s.ReadUint32(&y) || !s.ReadUint16(&z) {
+ t.Error("ReadUint8() = false, want true")
+ }
+ if x != 23 || y != 0xfffefdfc || z != 42 {
+ t.Errorf("x, y, z = %d, %d, %d; want 23, 4294901244, 5", x, y, z)
+ }
+ if len(s) != 0 {
+ t.Errorf("len(s) = %d, want 0", len(s))
+ }
+}
+
+func TestUint8LengthPrefixedSimple(t *testing.T) {
+ var b Builder
+ b.AddUint8LengthPrefixed(func(c *Builder) {
+ c.AddUint8(23)
+ c.AddUint8(42)
+ })
+ if err := builderBytesEq(&b, 2, 23, 42); err != nil {
+ t.Error(err)
+ }
+
+ var base, child String = b.BytesOrPanic(), nil
+ var x, y uint8
+ if !base.ReadUint8LengthPrefixed(&child) || !child.ReadUint8(&x) ||
+ !child.ReadUint8(&y) {
+ t.Error("parsing failed")
+ }
+ if x != 23 || y != 42 {
+ t.Errorf("want x, y == 23, 42; got %d, %d", x, y)
+ }
+ if len(base) != 0 {
+ t.Errorf("len(base) = %d, want 0", len(base))
+ }
+ if len(child) != 0 {
+ t.Errorf("len(child) = %d, want 0", len(child))
+ }
+}
+
+func TestUint8LengthPrefixedMulti(t *testing.T) {
+ var b Builder
+ b.AddUint8LengthPrefixed(func(c *Builder) {
+ c.AddUint8(23)
+ c.AddUint8(42)
+ })
+ b.AddUint8(5)
+ b.AddUint8LengthPrefixed(func(c *Builder) {
+ c.AddUint8(123)
+ c.AddUint8(234)
+ })
+ if err := builderBytesEq(&b, 2, 23, 42, 5, 2, 123, 234); err != nil {
+ t.Error(err)
+ }
+
+ var s, child String = b.BytesOrPanic(), nil
+ var u, v, w, x, y uint8
+ if !s.ReadUint8LengthPrefixed(&child) || !child.ReadUint8(&u) || !child.ReadUint8(&v) ||
+ !s.ReadUint8(&w) || !s.ReadUint8LengthPrefixed(&child) || !child.ReadUint8(&x) || !child.ReadUint8(&y) {
+ t.Error("parsing failed")
+ }
+ if u != 23 || v != 42 || w != 5 || x != 123 || y != 234 {
+ t.Errorf("u, v, w, x, y = %d, %d, %d, %d, %d; want 23, 42, 5, 123, 234",
+ u, v, w, x, y)
+ }
+ if len(s) != 0 {
+ t.Errorf("len(s) = %d, want 0", len(s))
+ }
+ if len(child) != 0 {
+ t.Errorf("len(child) = %d, want 0", len(child))
+ }
+}
+
+func TestUint8LengthPrefixedNested(t *testing.T) {
+ var b Builder
+ b.AddUint8LengthPrefixed(func(c *Builder) {
+ c.AddUint8(5)
+ c.AddUint8LengthPrefixed(func(d *Builder) {
+ d.AddUint8(23)
+ d.AddUint8(42)
+ })
+ c.AddUint8(123)
+ })
+ if err := builderBytesEq(&b, 5, 5, 2, 23, 42, 123); err != nil {
+ t.Error(err)
+ }
+
+ var base, child1, child2 String = b.BytesOrPanic(), nil, nil
+ var u, v, w, x uint8
+ if !base.ReadUint8LengthPrefixed(&child1) {
+ t.Error("parsing base failed")
+ }
+ if !child1.ReadUint8(&u) || !child1.ReadUint8LengthPrefixed(&child2) || !child1.ReadUint8(&x) {
+ t.Error("parsing child1 failed")
+ }
+ if !child2.ReadUint8(&v) || !child2.ReadUint8(&w) {
+ t.Error("parsing child2 failed")
+ }
+ if u != 5 || v != 23 || w != 42 || x != 123 {
+ t.Errorf("u, v, w, x = %d, %d, %d, %d, want 5, 23, 42, 123",
+ u, v, w, x)
+ }
+ if len(base) != 0 {
+ t.Errorf("len(base) = %d, want 0", len(base))
+ }
+ if len(child1) != 0 {
+ t.Errorf("len(child1) = %d, want 0", len(child1))
+ }
+ if len(base) != 0 {
+ t.Errorf("len(child2) = %d, want 0", len(child2))
+ }
+}
+
+func TestPreallocatedBuffer(t *testing.T) {
+ var buf [5]byte
+ b := NewBuilder(buf[0:0])
+ b.AddUint8(1)
+ b.AddUint8LengthPrefixed(func(c *Builder) {
+ c.AddUint8(3)
+ c.AddUint8(4)
+ })
+ b.AddUint16(1286) // Outgrow buf by one byte.
+ want := []byte{1, 2, 3, 4, 0}
+ if !bytes.Equal(buf[:], want) {
+ t.Errorf("buf = %v want %v", buf, want)
+ }
+ if err := builderBytesEq(b, 1, 2, 3, 4, 5, 6); err != nil {
+ t.Error(err)
+ }
+}
+
+func TestWriteWithPendingChild(t *testing.T) {
+ var b Builder
+ b.AddUint8LengthPrefixed(func(c *Builder) {
+ c.AddUint8LengthPrefixed(func(d *Builder) {
+ defer func() {
+ if recover() == nil {
+ t.Errorf("recover() = nil, want error; c.AddUint8() did not panic")
+ }
+ }()
+ c.AddUint8(2) // panics
+
+ defer func() {
+ if recover() == nil {
+ t.Errorf("recover() = nil, want error; b.AddUint8() did not panic")
+ }
+ }()
+ b.AddUint8(2) // panics
+ })
+
+ defer func() {
+ if recover() == nil {
+ t.Errorf("recover() = nil, want error; b.AddUint8() did not panic")
+ }
+ }()
+ b.AddUint8(2) // panics
+ })
+}
+
+// ASN.1
+
+func TestASN1Int64(t *testing.T) {
+ tests := []struct {
+ in int64
+ want []byte
+ }{
+ {-0x800000, []byte{2, 3, 128, 0, 0}},
+ {-256, []byte{2, 2, 255, 0}},
+ {-129, []byte{2, 2, 255, 127}},
+ {-128, []byte{2, 1, 128}},
+ {-1, []byte{2, 1, 255}},
+ {0, []byte{2, 1, 0}},
+ {1, []byte{2, 1, 1}},
+ {2, []byte{2, 1, 2}},
+ {127, []byte{2, 1, 127}},
+ {128, []byte{2, 2, 0, 128}},
+ {256, []byte{2, 2, 1, 0}},
+ {0x800000, []byte{2, 4, 0, 128, 0, 0}},
+ }
+ for i, tt := range tests {
+ var b Builder
+ b.AddASN1Int64(tt.in)
+ if err := builderBytesEq(&b, tt.want...); err != nil {
+ t.Errorf("%v, (i = %d; in = %v)", err, i, tt.in)
+ }
+
+ var n int64
+ s := String(b.BytesOrPanic())
+ ok := s.ReadASN1Integer(&n)
+ if !ok || n != tt.in {
+ t.Errorf("s.ReadASN1Integer(&n) = %v, n = %d; want true, n = %d (i = %d)",
+ ok, n, tt.in, i)
+ }
+ if len(s) != 0 {
+ t.Errorf("len(s) = %d, want 0", len(s))
+ }
+ }
+}
+
+func TestASN1Uint64(t *testing.T) {
+ tests := []struct {
+ in uint64
+ want []byte
+ }{
+ {0, []byte{2, 1, 0}},
+ {1, []byte{2, 1, 1}},
+ {2, []byte{2, 1, 2}},
+ {127, []byte{2, 1, 127}},
+ {128, []byte{2, 2, 0, 128}},
+ {256, []byte{2, 2, 1, 0}},
+ {0x800000, []byte{2, 4, 0, 128, 0, 0}},
+ {0x7fffffffffffffff, []byte{2, 8, 127, 255, 255, 255, 255, 255, 255, 255}},
+ {0x8000000000000000, []byte{2, 9, 0, 128, 0, 0, 0, 0, 0, 0, 0}},
+ {0xffffffffffffffff, []byte{2, 9, 0, 255, 255, 255, 255, 255, 255, 255, 255}},
+ }
+ for i, tt := range tests {
+ var b Builder
+ b.AddASN1Uint64(tt.in)
+ if err := builderBytesEq(&b, tt.want...); err != nil {
+ t.Errorf("%v, (i = %d; in = %v)", err, i, tt.in)
+ }
+
+ var n uint64
+ s := String(b.BytesOrPanic())
+ ok := s.ReadASN1Integer(&n)
+ if !ok || n != tt.in {
+ t.Errorf("s.ReadASN1Integer(&n) = %v, n = %d; want true, n = %d (i = %d)",
+ ok, n, tt.in, i)
+ }
+ if len(s) != 0 {
+ t.Errorf("len(s) = %d, want 0", len(s))
+ }
+ }
+}
diff --git a/vendor/golang.org/x/crypto/cryptobyte/example_test.go b/vendor/golang.org/x/crypto/cryptobyte/example_test.go
new file mode 100644
index 0000000000..7d3c06e120
--- /dev/null
+++ b/vendor/golang.org/x/crypto/cryptobyte/example_test.go
@@ -0,0 +1,120 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package cryptobyte_test
+
+import (
+ "encoding/asn1"
+ "fmt"
+ "golang.org/x/crypto/cryptobyte"
+)
+
+func ExampleString_lengthPrefixed() {
+ // This is an example of parsing length-prefixed data (as found in, for
+ // example, TLS). Imagine a 16-bit prefixed series of 8-bit prefixed
+ // strings.
+
+ input := cryptobyte.String([]byte{0, 12, 5, 'h', 'e', 'l', 'l', 'o', 5, 'w', 'o', 'r', 'l', 'd'})
+ var result []string
+
+ var values cryptobyte.String
+ if !input.ReadUint16LengthPrefixed(&values) ||
+ !input.Empty() {
+ panic("bad format")
+ }
+
+ for !values.Empty() {
+ var value cryptobyte.String
+ if !values.ReadUint8LengthPrefixed(&value) {
+ panic("bad format")
+ }
+
+ result = append(result, string(value))
+ }
+
+ // Output: []string{"hello", "world"}
+ fmt.Printf("%#v\n", result)
+}
+
+func ExampleString_asn1() {
+ // This is an example of parsing ASN.1 data that looks like:
+ // Foo ::= SEQUENCE {
+ // version [6] INTEGER DEFAULT 0
+ // data OCTET STRING
+ // }
+
+ input := cryptobyte.String([]byte{0x30, 12, 0xa6, 3, 2, 1, 2, 4, 5, 'h', 'e', 'l', 'l', 'o'})
+
+ var (
+ version int64
+ data, inner, versionBytes cryptobyte.String
+ haveVersion bool
+ )
+ if !input.ReadASN1(&inner, cryptobyte.Tag(asn1.TagSequence).Constructed()) ||
+ !input.Empty() ||
+ !inner.ReadOptionalASN1(&versionBytes, &haveVersion, cryptobyte.Tag(6).Constructed().ContextSpecific()) ||
+ (haveVersion && !versionBytes.ReadASN1Integer(&version)) ||
+ (haveVersion && !versionBytes.Empty()) ||
+ !inner.ReadASN1(&data, asn1.TagOctetString) ||
+ !inner.Empty() {
+ panic("bad format")
+ }
+
+ // Output: haveVersion: true, version: 2, data: hello
+ fmt.Printf("haveVersion: %t, version: %d, data: %s\n", haveVersion, version, string(data))
+}
+
+func ExampleBuilder_asn1() {
+ // This is an example of building ASN.1 data that looks like:
+ // Foo ::= SEQUENCE {
+ // version [6] INTEGER DEFAULT 0
+ // data OCTET STRING
+ // }
+
+ version := int64(2)
+ data := []byte("hello")
+ const defaultVersion = 0
+
+ var b cryptobyte.Builder
+ b.AddASN1(cryptobyte.Tag(asn1.TagSequence).Constructed(), func(b *cryptobyte.Builder) {
+ if version != defaultVersion {
+ b.AddASN1(cryptobyte.Tag(6).Constructed().ContextSpecific(), func(b *cryptobyte.Builder) {
+ b.AddASN1Int64(version)
+ })
+ }
+ b.AddASN1OctetString(data)
+ })
+
+ result, err := b.Bytes()
+ if err != nil {
+ panic(err)
+ }
+
+ // Output: 300ca603020102040568656c6c6f
+ fmt.Printf("%x\n", result)
+}
+
+func ExampleBuilder_lengthPrefixed() {
+ // This is an example of building length-prefixed data (as found in,
+ // for example, TLS). Imagine a 16-bit prefixed series of 8-bit
+ // prefixed strings.
+ input := []string{"hello", "world"}
+
+ var b cryptobyte.Builder
+ b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
+ for _, value := range input {
+ b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) {
+ b.AddBytes([]byte(value))
+ })
+ }
+ })
+
+ result, err := b.Bytes()
+ if err != nil {
+ panic(err)
+ }
+
+ // Output: 000c0568656c6c6f05776f726c64
+ fmt.Printf("%x\n", result)
+}
diff --git a/vendor/golang.org/x/crypto/cryptobyte/string.go b/vendor/golang.org/x/crypto/cryptobyte/string.go
new file mode 100644
index 0000000000..b1215b3bf8
--- /dev/null
+++ b/vendor/golang.org/x/crypto/cryptobyte/string.go
@@ -0,0 +1,157 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package cryptobyte implements building and parsing of byte strings for
+// DER-encoded ASN.1 and TLS messages. See the examples for the Builder and
+// String types to get started.
+package cryptobyte
+
+// String represents a string of bytes. It provides methods for parsing
+// fixed-length and length-prefixed values from it.
+type String []byte
+
+// read advances a String by n bytes and returns them. If less than n bytes
+// remain, it returns nil.
+func (s *String) read(n int) []byte {
+ if len(*s) < n {
+ return nil
+ }
+ v := (*s)[:n]
+ *s = (*s)[n:]
+ return v
+}
+
+// Skip advances the String by n byte and reports whether it was successful.
+func (s *String) Skip(n int) bool {
+ return s.read(n) != nil
+}
+
+// ReadUint8 decodes an 8-bit value into out and advances over it. It
+// returns true on success and false on error.
+func (s *String) ReadUint8(out *uint8) bool {
+ v := s.read(1)
+ if v == nil {
+ return false
+ }
+ *out = uint8(v[0])
+ return true
+}
+
+// ReadUint16 decodes a big-endian, 16-bit value into out and advances over it.
+// It returns true on success and false on error.
+func (s *String) ReadUint16(out *uint16) bool {
+ v := s.read(2)
+ if v == nil {
+ return false
+ }
+ *out = uint16(v[0])<<8 | uint16(v[1])
+ return true
+}
+
+// ReadUint24 decodes a big-endian, 24-bit value into out and advances over it.
+// It returns true on success and false on error.
+func (s *String) ReadUint24(out *uint32) bool {
+ v := s.read(3)
+ if v == nil {
+ return false
+ }
+ *out = uint32(v[0])<<16 | uint32(v[1])<<8 | uint32(v[2])
+ return true
+}
+
+// ReadUint32 decodes a big-endian, 32-bit value into out and advances over it.
+// It returns true on success and false on error.
+func (s *String) ReadUint32(out *uint32) bool {
+ v := s.read(4)
+ if v == nil {
+ return false
+ }
+ *out = uint32(v[0])<<24 | uint32(v[1])<<16 | uint32(v[2])<<8 | uint32(v[3])
+ return true
+}
+
+func (s *String) readUnsigned(out *uint32, length int) bool {
+ v := s.read(length)
+ if v == nil {
+ return false
+ }
+ var result uint32
+ for i := 0; i < length; i++ {
+ result <<= 8
+ result |= uint32(v[i])
+ }
+ *out = result
+ return true
+}
+
+func (s *String) readLengthPrefixed(lenLen int, outChild *String) bool {
+ lenBytes := s.read(lenLen)
+ if lenBytes == nil {
+ return false
+ }
+ var length uint32
+ for _, b := range lenBytes {
+ length = length << 8
+ length = length | uint32(b)
+ }
+ if int(length) < 0 {
+ // This currently cannot overflow because we read uint24 at most, but check
+ // anyway in case that changes in the future.
+ return false
+ }
+ v := s.read(int(length))
+ if v == nil {
+ return false
+ }
+ *outChild = v
+ return true
+}
+
+// ReadUint8LengthPrefixed reads the content of an 8-bit length-prefixed value
+// into out and advances over it. It returns true on success and false on
+// error.
+func (s *String) ReadUint8LengthPrefixed(out *String) bool {
+ return s.readLengthPrefixed(1, out)
+}
+
+// ReadUint16LengthPrefixed reads the content of a big-endian, 16-bit
+// length-prefixed value into out and advances over it. It returns true on
+// success and false on error.
+func (s *String) ReadUint16LengthPrefixed(out *String) bool {
+ return s.readLengthPrefixed(2, out)
+}
+
+// ReadUint24LengthPrefixed reads the content of a big-endian, 24-bit
+// length-prefixed value into out and advances over it. It returns true on
+// success and false on error.
+func (s *String) ReadUint24LengthPrefixed(out *String) bool {
+ return s.readLengthPrefixed(3, out)
+}
+
+// ReadBytes reads n bytes into out and advances over them. It returns true on
+// success and false and error.
+func (s *String) ReadBytes(out *[]byte, n int) bool {
+ v := s.read(n)
+ if v == nil {
+ return false
+ }
+ *out = v
+ return true
+}
+
+// CopyBytes copies len(out) bytes into out and advances over them. It returns
+// true on success and false on error.
+func (s *String) CopyBytes(out []byte) bool {
+ n := len(out)
+ v := s.read(n)
+ if v == nil {
+ return false
+ }
+ return copy(out, v) == n
+}
+
+// Empty reports whether the string does not contain any bytes.
+func (s String) Empty() bool {
+ return len(s) == 0
+}
diff --git a/vendor/golang.org/x/crypto/curve25519/const_amd64.h b/vendor/golang.org/x/crypto/curve25519/const_amd64.h
new file mode 100644
index 0000000000..80ad2220fd
--- /dev/null
+++ b/vendor/golang.org/x/crypto/curve25519/const_amd64.h
@@ -0,0 +1,8 @@
+// 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.
+
+// This code was translated into a form compatible with 6a from the public
+// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
+
+#define REDMASK51 0x0007FFFFFFFFFFFF
diff --git a/vendor/golang.org/x/crypto/curve25519/const_amd64.s b/vendor/golang.org/x/crypto/curve25519/const_amd64.s
index 797f9b051d..0ad539885b 100644
--- a/vendor/golang.org/x/crypto/curve25519/const_amd64.s
+++ b/vendor/golang.org/x/crypto/curve25519/const_amd64.s
@@ -7,8 +7,8 @@
// +build amd64,!gccgo,!appengine
-DATA ·REDMASK51(SB)/8, $0x0007FFFFFFFFFFFF
-GLOBL ·REDMASK51(SB), 8, $8
+// These constants cannot be encoded in non-MOVQ immediates.
+// We access them directly from memory instead.
DATA ·_121666_213(SB)/8, $996687872
GLOBL ·_121666_213(SB), 8, $8
diff --git a/vendor/golang.org/x/crypto/curve25519/freeze_amd64.s b/vendor/golang.org/x/crypto/curve25519/freeze_amd64.s
index 932800b8d1..536479bf62 100644
--- a/vendor/golang.org/x/crypto/curve25519/freeze_amd64.s
+++ b/vendor/golang.org/x/crypto/curve25519/freeze_amd64.s
@@ -7,6 +7,8 @@
// +build amd64,!gccgo,!appengine
+#include "const_amd64.h"
+
// func freeze(inout *[5]uint64)
TEXT ·freeze(SB),7,$0-8
MOVQ inout+0(FP), DI
@@ -16,7 +18,7 @@ TEXT ·freeze(SB),7,$0-8
MOVQ 16(DI),CX
MOVQ 24(DI),R8
MOVQ 32(DI),R9
- MOVQ ·REDMASK51(SB),AX
+ MOVQ $REDMASK51,AX
MOVQ AX,R10
SUBQ $18,R10
MOVQ $3,R11
diff --git a/vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s b/vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s
index ee7b36c368..7074e5cd9d 100644
--- a/vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s
+++ b/vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s
@@ -7,6 +7,8 @@
// +build amd64,!gccgo,!appengine
+#include "const_amd64.h"
+
// func ladderstep(inout *[5][5]uint64)
TEXT ·ladderstep(SB),0,$296-8
MOVQ inout+0(FP),DI
@@ -118,7 +120,7 @@ TEXT ·ladderstep(SB),0,$296-8
MULQ 72(SP)
ADDQ AX,R12
ADCQ DX,R13
- MOVQ ·REDMASK51(SB),DX
+ MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R9:R8
@@ -233,7 +235,7 @@ TEXT ·ladderstep(SB),0,$296-8
MULQ 32(SP)
ADDQ AX,R12
ADCQ DX,R13
- MOVQ ·REDMASK51(SB),DX
+ MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R9:R8
@@ -438,7 +440,7 @@ TEXT ·ladderstep(SB),0,$296-8
MULQ 72(SP)
ADDQ AX,R12
ADCQ DX,R13
- MOVQ ·REDMASK51(SB),DX
+ MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R9:R8
@@ -588,7 +590,7 @@ TEXT ·ladderstep(SB),0,$296-8
MULQ 32(SP)
ADDQ AX,R12
ADCQ DX,R13
- MOVQ ·REDMASK51(SB),DX
+ MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R9:R8
@@ -728,7 +730,7 @@ TEXT ·ladderstep(SB),0,$296-8
MULQ 152(DI)
ADDQ AX,R12
ADCQ DX,R13
- MOVQ ·REDMASK51(SB),DX
+ MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R9:R8
@@ -843,7 +845,7 @@ TEXT ·ladderstep(SB),0,$296-8
MULQ 192(DI)
ADDQ AX,R12
ADCQ DX,R13
- MOVQ ·REDMASK51(SB),DX
+ MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R9:R8
@@ -993,7 +995,7 @@ TEXT ·ladderstep(SB),0,$296-8
MULQ 32(DI)
ADDQ AX,R12
ADCQ DX,R13
- MOVQ ·REDMASK51(SB),DX
+ MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R9:R8
@@ -1143,7 +1145,7 @@ TEXT ·ladderstep(SB),0,$296-8
MULQ 112(SP)
ADDQ AX,R12
ADCQ DX,R13
- MOVQ ·REDMASK51(SB),DX
+ MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R9:R8
@@ -1329,7 +1331,7 @@ TEXT ·ladderstep(SB),0,$296-8
MULQ 192(SP)
ADDQ AX,R12
ADCQ DX,R13
- MOVQ ·REDMASK51(SB),DX
+ MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R9:R8
diff --git a/vendor/golang.org/x/crypto/curve25519/mul_amd64.s b/vendor/golang.org/x/crypto/curve25519/mul_amd64.s
index 33ce57dcde..b162e65159 100644
--- a/vendor/golang.org/x/crypto/curve25519/mul_amd64.s
+++ b/vendor/golang.org/x/crypto/curve25519/mul_amd64.s
@@ -7,6 +7,8 @@
// +build amd64,!gccgo,!appengine
+#include "const_amd64.h"
+
// func mul(dest, a, b *[5]uint64)
TEXT ·mul(SB),0,$16-24
MOVQ dest+0(FP), DI
@@ -121,7 +123,7 @@ TEXT ·mul(SB),0,$16-24
MULQ 32(CX)
ADDQ AX,R14
ADCQ DX,R15
- MOVQ ·REDMASK51(SB),SI
+ MOVQ $REDMASK51,SI
SHLQ $13,R9:R8
ANDQ SI,R8
SHLQ $13,R11:R10
diff --git a/vendor/golang.org/x/crypto/curve25519/square_amd64.s b/vendor/golang.org/x/crypto/curve25519/square_amd64.s
index 3a92804ddf..4e864a83ef 100644
--- a/vendor/golang.org/x/crypto/curve25519/square_amd64.s
+++ b/vendor/golang.org/x/crypto/curve25519/square_amd64.s
@@ -7,6 +7,8 @@
// +build amd64,!gccgo,!appengine
+#include "const_amd64.h"
+
// func square(out, in *[5]uint64)
TEXT ·square(SB),7,$0-16
MOVQ out+0(FP), DI
@@ -84,7 +86,7 @@ TEXT ·square(SB),7,$0-16
MULQ 32(SI)
ADDQ AX,R13
ADCQ DX,R14
- MOVQ ·REDMASK51(SB),SI
+ MOVQ $REDMASK51,SI
SHLQ $13,R8:CX
ANDQ SI,CX
SHLQ $13,R10:R9
diff --git a/vendor/golang.org/x/crypto/ocsp/ocsp_test.go b/vendor/golang.org/x/crypto/ocsp/ocsp_test.go
index a3c8986194..d325d851eb 100644
--- a/vendor/golang.org/x/crypto/ocsp/ocsp_test.go
+++ b/vendor/golang.org/x/crypto/ocsp/ocsp_test.go
@@ -225,7 +225,6 @@ func TestOCSPResponse(t *testing.T) {
},
}
- producedAt := time.Now().Truncate(time.Minute)
thisUpdate := time.Date(2010, 7, 7, 15, 1, 5, 0, time.UTC)
nextUpdate := time.Date(2010, 7, 7, 18, 35, 17, 0, time.UTC)
template := Response{
@@ -284,8 +283,9 @@ func TestOCSPResponse(t *testing.T) {
t.Errorf("resp.Extensions: got %v, want %v", resp.Extensions, template.ExtraExtensions)
}
- if !resp.ProducedAt.Equal(producedAt) {
- t.Errorf("resp.ProducedAt: got %d, want %d", resp.ProducedAt, producedAt)
+ delay := time.Since(resp.ProducedAt)
+ if delay < -time.Hour || delay > time.Hour {
+ t.Errorf("resp.ProducedAt: got %s, want close to current time (%s)", resp.ProducedAt, time.Now())
}
if resp.Status != template.Status {
diff --git a/vendor/golang.org/x/crypto/poly1305/poly1305_test.go b/vendor/golang.org/x/crypto/poly1305/poly1305_test.go
index 7b8ab2fe16..017027fe6e 100644
--- a/vendor/golang.org/x/crypto/poly1305/poly1305_test.go
+++ b/vendor/golang.org/x/crypto/poly1305/poly1305_test.go
@@ -6,10 +6,14 @@ package poly1305
import (
"bytes"
+ "encoding/hex"
+ "flag"
"testing"
"unsafe"
)
+var stressFlag = flag.Bool("stress", false, "run slow stress tests")
+
var testData = []struct {
in, k, correct []byte
}{
@@ -88,6 +92,39 @@ func testSum(t *testing.T, unaligned bool) {
}
}
+func TestBurnin(t *testing.T) {
+ // This test can be used to sanity-check significant changes. It can
+ // take about many minutes to run, even on fast machines. It's disabled
+ // by default.
+ if !*stressFlag {
+ t.Skip("skipping without -stress")
+ }
+
+ var key [32]byte
+ var input [25]byte
+ var output [16]byte
+
+ for i := range key {
+ key[i] = 1
+ }
+ for i := range input {
+ input[i] = 2
+ }
+
+ for i := uint64(0); i < 1e10; i++ {
+ Sum(&output, input[:], &key)
+ copy(key[0:], output[:])
+ copy(key[16:], output[:])
+ copy(input[:], output[:])
+ copy(input[16:], output[:])
+ }
+
+ const expected = "5e3b866aea0b636d240c83c428f84bfa"
+ if got := hex.EncodeToString(output[:]); got != expected {
+ t.Errorf("expected %s, got %s", expected, got)
+ }
+}
+
func TestSum(t *testing.T) { testSum(t, false) }
func TestSumUnaligned(t *testing.T) { testSum(t, true) }
diff --git a/vendor/golang.org/x/crypto/poly1305/sum_ref.go b/vendor/golang.org/x/crypto/poly1305/sum_ref.go
index dbe50e78a0..b2805a5ca1 100644
--- a/vendor/golang.org/x/crypto/poly1305/sum_ref.go
+++ b/vendor/golang.org/x/crypto/poly1305/sum_ref.go
@@ -6,1526 +6,136 @@
package poly1305
-// Based on original, public domain implementation from NaCl by D. J.
-// Bernstein.
+import "encoding/binary"
-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
+// Sum generates an authenticator for msg using a one-time key and puts the
// 16-byte result into out. Authenticating two different messages with the same
// key allows an attacker to forge messages at will.
-func Sum(out *[16]byte, m []byte, key *[32]byte) {
- r := key
- s := key[16:]
+func Sum(out *[TagSize]byte, msg []byte, key *[32]byte) {
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
+ h0, h1, h2, h3, h4 uint32 // the hash accumulators
+ r0, r1, r2, r3, r4 uint64 // the r part of the key
)
- var p int32
+ r0 = uint64(binary.LittleEndian.Uint32(key[0:]) & 0x3ffffff)
+ r1 = uint64((binary.LittleEndian.Uint32(key[3:]) >> 2) & 0x3ffff03)
+ r2 = uint64((binary.LittleEndian.Uint32(key[6:]) >> 4) & 0x3ffc0ff)
+ r3 = uint64((binary.LittleEndian.Uint32(key[9:]) >> 6) & 0x3f03fff)
+ r4 = uint64((binary.LittleEndian.Uint32(key[12:]) >> 8) & 0x00fffff)
- l := int32(len(m))
+ R1, R2, R3, R4 := r1*5, r2*5, r3*5, r4*5
- r00 := uint32(r[0])
+ for len(msg) >= TagSize {
+ // h += msg
+ h0 += binary.LittleEndian.Uint32(msg[0:]) & 0x3ffffff
+ h1 += (binary.LittleEndian.Uint32(msg[3:]) >> 2) & 0x3ffffff
+ h2 += (binary.LittleEndian.Uint32(msg[6:]) >> 4) & 0x3ffffff
+ h3 += (binary.LittleEndian.Uint32(msg[9:]) >> 6) & 0x3ffffff
+ h4 += (binary.LittleEndian.Uint32(msg[12:]) >> 8) | (1 << 24)
- r01 := uint32(r[1])
+ // h *= r
+ d0 := (uint64(h0) * r0) + (uint64(h1) * R4) + (uint64(h2) * R3) + (uint64(h3) * R2) + (uint64(h4) * R1)
+ d1 := (d0 >> 26) + (uint64(h0) * r1) + (uint64(h1) * r0) + (uint64(h2) * R4) + (uint64(h3) * R3) + (uint64(h4) * R2)
+ d2 := (d1 >> 26) + (uint64(h0) * r2) + (uint64(h1) * r1) + (uint64(h2) * r0) + (uint64(h3) * R4) + (uint64(h4) * R3)
+ d3 := (d2 >> 26) + (uint64(h0) * r3) + (uint64(h1) * r2) + (uint64(h2) * r1) + (uint64(h3) * r0) + (uint64(h4) * R4)
+ d4 := (d3 >> 26) + (uint64(h0) * r4) + (uint64(h1) * r3) + (uint64(h2) * r2) + (uint64(h3) * r1) + (uint64(h4) * r0)
- r02 := uint32(r[2])
- r0 := int64(2151)
+ // h %= p
+ h0 = uint32(d0) & 0x3ffffff
+ h1 = uint32(d1) & 0x3ffffff
+ h2 = uint32(d2) & 0x3ffffff
+ h3 = uint32(d3) & 0x3ffffff
+ h4 = uint32(d4) & 0x3ffffff
- r03 := uint32(r[3])
- r03 &= 15
- r0 <<= 51
+ h0 += uint32(d4>>26) * 5
+ h1 += h0 >> 26
+ h0 = h0 & 0x3ffffff
- 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
+ msg = msg[TagSize:]
}
- m00 = uint32(m[p+0])
- m0 = 2151
+ if len(msg) > 0 {
+ var block [TagSize]byte
+ off := copy(block[:], msg)
+ block[off] = 0x01
- m0 <<= 51
- m1 = 2215
- m01 = uint32(m[p+1])
+ // h += msg
+ h0 += binary.LittleEndian.Uint32(block[0:]) & 0x3ffffff
+ h1 += (binary.LittleEndian.Uint32(block[3:]) >> 2) & 0x3ffffff
+ h2 += (binary.LittleEndian.Uint32(block[6:]) >> 4) & 0x3ffffff
+ h3 += (binary.LittleEndian.Uint32(block[9:]) >> 6) & 0x3ffffff
+ h4 += (binary.LittleEndian.Uint32(block[12:]) >> 8)
- m1 <<= 51
- m2 = 2279
- m02 = uint32(m[p+2])
+ // h *= r
+ d0 := (uint64(h0) * r0) + (uint64(h1) * R4) + (uint64(h2) * R3) + (uint64(h3) * R2) + (uint64(h4) * R1)
+ d1 := (d0 >> 26) + (uint64(h0) * r1) + (uint64(h1) * r0) + (uint64(h2) * R4) + (uint64(h3) * R3) + (uint64(h4) * R2)
+ d2 := (d1 >> 26) + (uint64(h0) * r2) + (uint64(h1) * r1) + (uint64(h2) * r0) + (uint64(h3) * R4) + (uint64(h4) * R3)
+ d3 := (d2 >> 26) + (uint64(h0) * r3) + (uint64(h1) * r2) + (uint64(h2) * r1) + (uint64(h3) * r0) + (uint64(h4) * R4)
+ d4 := (d3 >> 26) + (uint64(h0) * r4) + (uint64(h1) * r3) + (uint64(h2) * r2) + (uint64(h3) * r1) + (uint64(h4) * r0)
- m2 <<= 51
- m3 = 2343
- m03 = uint32(m[p+3])
+ // h %= p
+ h0 = uint32(d0) & 0x3ffffff
+ h1 = uint32(d1) & 0x3ffffff
+ h2 = uint32(d2) & 0x3ffffff
+ h3 = uint32(d3) & 0x3ffffff
+ h4 = uint32(d4) & 0x3ffffff
- 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
+ h0 += uint32(d4>>26) * 5
+ h1 += h0 >> 26
+ h0 = h0 & 0x3ffffff
}
-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)
+ // h %= p reduction
+ h2 += h1 >> 26
+ h1 &= 0x3ffffff
+ h3 += h2 >> 26
+ h2 &= 0x3ffffff
+ h4 += h3 >> 26
+ h3 &= 0x3ffffff
+ h0 += 5 * (h4 >> 26)
+ h4 &= 0x3ffffff
+ h1 += h0 >> 26
+ h0 &= 0x3ffffff
+
+ // h - p
+ t0 := h0 + 5
+ t1 := h1 + (t0 >> 26)
+ t2 := h2 + (t1 >> 26)
+ t3 := h3 + (t2 >> 26)
+ t4 := h4 + (t3 >> 26) - (1 << 26)
+ t0 &= 0x3ffffff
+ t1 &= 0x3ffffff
+ t2 &= 0x3ffffff
+ t3 &= 0x3ffffff
+
+ // select h if h < p else h - p
+ t_mask := (t4 >> 31) - 1
+ h_mask := ^t_mask
+ h0 = (h0 & h_mask) | (t0 & t_mask)
+ h1 = (h1 & h_mask) | (t1 & t_mask)
+ h2 = (h2 & h_mask) | (t2 & t_mask)
+ h3 = (h3 & h_mask) | (t3 & t_mask)
+ h4 = (h4 & h_mask) | (t4 & t_mask)
+
+ // h %= 2^128
+ h0 |= h1 << 26
+ h1 = ((h1 >> 6) | (h2 << 20))
+ h2 = ((h2 >> 12) | (h3 << 14))
+ h3 = ((h3 >> 18) | (h4 << 8))
+
+ // s: the s part of the key
+ // tag = (h + s) % (2^128)
+ t := uint64(h0) + uint64(binary.LittleEndian.Uint32(key[16:]))
+ h0 = uint32(t)
+ t = uint64(h1) + uint64(binary.LittleEndian.Uint32(key[20:])) + (t >> 32)
+ h1 = uint32(t)
+ t = uint64(h2) + uint64(binary.LittleEndian.Uint32(key[24:])) + (t >> 32)
+ h2 = uint32(t)
+ t = uint64(h3) + uint64(binary.LittleEndian.Uint32(key[28:])) + (t >> 32)
+ h3 = uint32(t)
+
+ binary.LittleEndian.PutUint32(out[0:], h0)
+ binary.LittleEndian.PutUint32(out[4:], h1)
+ binary.LittleEndian.PutUint32(out[8:], h2)
+ binary.LittleEndian.PutUint32(out[12:], h3)
}
diff --git a/vendor/golang.org/x/crypto/ssh/agent/client_test.go b/vendor/golang.org/x/crypto/ssh/agent/client_test.go
index e33d471380..a13a650017 100644
--- a/vendor/golang.org/x/crypto/ssh/agent/client_test.go
+++ b/vendor/golang.org/x/crypto/ssh/agent/client_test.go
@@ -180,7 +180,7 @@ func TestCert(t *testing.T) {
// therefore is buffered (net.Pipe deadlocks if both sides start with
// a write.)
func netPipe() (net.Conn, net.Conn, error) {
- listener, err := net.Listen("tcp", "127.0.0.1:0")
+ listener, err := net.Listen("tcp", ":0")
if err != nil {
return nil, nil, err
}
diff --git a/vendor/golang.org/x/crypto/ssh/cipher.go b/vendor/golang.org/x/crypto/ssh/cipher.go
index 34d3917c4f..13484ab4b3 100644
--- a/vendor/golang.org/x/crypto/ssh/cipher.go
+++ b/vendor/golang.org/x/crypto/ssh/cipher.go
@@ -135,6 +135,7 @@ const prefixLen = 5
type streamPacketCipher struct {
mac hash.Hash
cipher cipher.Stream
+ etm bool
// The following members are to avoid per-packet allocations.
prefix [prefixLen]byte
@@ -150,7 +151,14 @@ func (s *streamPacketCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, err
return nil, err
}
- s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
+ var encryptedPaddingLength [1]byte
+ if s.mac != nil && s.etm {
+ copy(encryptedPaddingLength[:], s.prefix[4:5])
+ s.cipher.XORKeyStream(s.prefix[4:5], s.prefix[4:5])
+ } else {
+ s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
+ }
+
length := binary.BigEndian.Uint32(s.prefix[0:4])
paddingLength := uint32(s.prefix[4])
@@ -159,7 +167,12 @@ func (s *streamPacketCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, err
s.mac.Reset()
binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum)
s.mac.Write(s.seqNumBytes[:])
- s.mac.Write(s.prefix[:])
+ if s.etm {
+ s.mac.Write(s.prefix[:4])
+ s.mac.Write(encryptedPaddingLength[:])
+ } else {
+ s.mac.Write(s.prefix[:])
+ }
macSize = uint32(s.mac.Size())
}
@@ -184,10 +197,17 @@ func (s *streamPacketCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, err
}
mac := s.packetData[length-1:]
data := s.packetData[:length-1]
+
+ if s.mac != nil && s.etm {
+ s.mac.Write(data)
+ }
+
s.cipher.XORKeyStream(data, data)
if s.mac != nil {
- s.mac.Write(data)
+ if !s.etm {
+ s.mac.Write(data)
+ }
s.macResult = s.mac.Sum(s.macResult[:0])
if subtle.ConstantTimeCompare(s.macResult, mac) != 1 {
return nil, errors.New("ssh: MAC failure")
@@ -203,7 +223,13 @@ func (s *streamPacketCipher) writePacket(seqNum uint32, w io.Writer, rand io.Rea
return errors.New("ssh: packet too large")
}
- paddingLength := packetSizeMultiple - (prefixLen+len(packet))%packetSizeMultiple
+ aadlen := 0
+ if s.mac != nil && s.etm {
+ // packet length is not encrypted for EtM modes
+ aadlen = 4
+ }
+
+ paddingLength := packetSizeMultiple - (prefixLen+len(packet)-aadlen)%packetSizeMultiple
if paddingLength < 4 {
paddingLength += packetSizeMultiple
}
@@ -220,15 +246,37 @@ func (s *streamPacketCipher) writePacket(seqNum uint32, w io.Writer, rand io.Rea
s.mac.Reset()
binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum)
s.mac.Write(s.seqNumBytes[:])
+
+ if s.etm {
+ // For EtM algorithms, the packet length must stay unencrypted,
+ // but the following data (padding length) must be encrypted
+ s.cipher.XORKeyStream(s.prefix[4:5], s.prefix[4:5])
+ }
+
s.mac.Write(s.prefix[:])
+
+ if !s.etm {
+ // For non-EtM algorithms, the algorithm is applied on unencrypted data
+ s.mac.Write(packet)
+ s.mac.Write(padding)
+ }
+ }
+
+ if !(s.mac != nil && s.etm) {
+ // For EtM algorithms, the padding length has already been encrypted
+ // and the packet length must remain unencrypted
+ s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
+ }
+
+ s.cipher.XORKeyStream(packet, packet)
+ s.cipher.XORKeyStream(padding, padding)
+
+ if s.mac != nil && s.etm {
+ // For EtM algorithms, packet and padding must be encrypted
s.mac.Write(packet)
s.mac.Write(padding)
}
- s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
- s.cipher.XORKeyStream(packet, packet)
- s.cipher.XORKeyStream(padding, padding)
-
if _, err := w.Write(s.prefix[:]); err != nil {
return err
}
diff --git a/vendor/golang.org/x/crypto/ssh/cipher_test.go b/vendor/golang.org/x/crypto/ssh/cipher_test.go
index eced8d851c..5cfa17a62d 100644
--- a/vendor/golang.org/x/crypto/ssh/cipher_test.go
+++ b/vendor/golang.org/x/crypto/ssh/cipher_test.go
@@ -26,39 +26,41 @@ func TestPacketCiphers(t *testing.T) {
defer delete(cipherModes, aes128cbcID)
for cipher := range cipherModes {
- kr := &kexResult{Hash: crypto.SHA1}
- algs := directionAlgorithms{
- Cipher: cipher,
- MAC: "hmac-sha1",
- Compression: "none",
- }
- client, err := newPacketCipher(clientKeys, algs, kr)
- if err != nil {
- t.Errorf("newPacketCipher(client, %q): %v", cipher, err)
- continue
- }
- server, err := newPacketCipher(clientKeys, algs, kr)
- if err != nil {
- t.Errorf("newPacketCipher(client, %q): %v", cipher, err)
- continue
- }
+ for mac := range macModes {
+ kr := &kexResult{Hash: crypto.SHA1}
+ algs := directionAlgorithms{
+ Cipher: cipher,
+ MAC: mac,
+ Compression: "none",
+ }
+ client, err := newPacketCipher(clientKeys, algs, kr)
+ if err != nil {
+ t.Errorf("newPacketCipher(client, %q, %q): %v", cipher, mac, err)
+ continue
+ }
+ server, err := newPacketCipher(clientKeys, algs, kr)
+ if err != nil {
+ t.Errorf("newPacketCipher(client, %q, %q): %v", cipher, mac, err)
+ continue
+ }
- want := "bla bla"
- input := []byte(want)
- buf := &bytes.Buffer{}
- if err := client.writePacket(0, buf, rand.Reader, input); err != nil {
- t.Errorf("writePacket(%q): %v", cipher, err)
- continue
- }
+ want := "bla bla"
+ input := []byte(want)
+ buf := &bytes.Buffer{}
+ if err := client.writePacket(0, buf, rand.Reader, input); err != nil {
+ t.Errorf("writePacket(%q, %q): %v", cipher, mac, err)
+ continue
+ }
- packet, err := server.readPacket(0, buf)
- if err != nil {
- t.Errorf("readPacket(%q): %v", cipher, err)
- continue
- }
+ packet, err := server.readPacket(0, buf)
+ if err != nil {
+ t.Errorf("readPacket(%q, %q): %v", cipher, mac, err)
+ continue
+ }
- if string(packet) != want {
- t.Errorf("roundtrip(%q): got %q, want %q", cipher, packet, want)
+ if string(packet) != want {
+ t.Errorf("roundtrip(%q, %q): got %q, want %q", cipher, mac, packet, want)
+ }
}
}
}
diff --git a/vendor/golang.org/x/crypto/ssh/client_auth_test.go b/vendor/golang.org/x/crypto/ssh/client_auth_test.go
index 1d9681a06c..e384c796b7 100644
--- a/vendor/golang.org/x/crypto/ssh/client_auth_test.go
+++ b/vendor/golang.org/x/crypto/ssh/client_auth_test.go
@@ -333,14 +333,14 @@ func TestClientLoginCert(t *testing.T) {
}
// allowed source address
- cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42/24"}
+ cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42/24,::42/120"}
cert.SignCert(rand.Reader, testSigners["ecdsa"])
if err := tryAuth(t, clientConfig); err != nil {
t.Errorf("cert login with source-address failed: %v", err)
}
// disallowed source address
- cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42"}
+ cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42,::42"}
cert.SignCert(rand.Reader, testSigners["ecdsa"])
if err := tryAuth(t, clientConfig); err == nil {
t.Errorf("cert login with source-address succeeded")
diff --git a/vendor/golang.org/x/crypto/ssh/common.go b/vendor/golang.org/x/crypto/ssh/common.go
index faabb7ef96..8656d0f85d 100644
--- a/vendor/golang.org/x/crypto/ssh/common.go
+++ b/vendor/golang.org/x/crypto/ssh/common.go
@@ -56,7 +56,7 @@ var supportedHostKeyAlgos = []string{
// This is based on RFC 4253, section 6.4, but with hmac-md5 variants removed
// because they have reached the end of their useful life.
var supportedMACs = []string{
- "hmac-sha2-256", "hmac-sha1", "hmac-sha1-96",
+ "hmac-sha2-256-etm@openssh.com", "hmac-sha2-256", "hmac-sha1", "hmac-sha1-96",
}
var supportedCompressions = []string{compressionNone}
diff --git a/vendor/golang.org/x/crypto/ssh/handshake.go b/vendor/golang.org/x/crypto/ssh/handshake.go
index 57f2d3daf6..8de650644a 100644
--- a/vendor/golang.org/x/crypto/ssh/handshake.go
+++ b/vendor/golang.org/x/crypto/ssh/handshake.go
@@ -66,8 +66,8 @@ type handshakeTransport struct {
// If the read loop wants to schedule a kex, it pings this
// channel, and the write loop will send out a kex
- // message. The boolean is whether this is the first request or not.
- requestKex chan bool
+ // message.
+ requestKex chan struct{}
// If the other side requests or confirms a kex, its kexInit
// packet is sent here for the write loop to find it.
@@ -102,14 +102,14 @@ func newHandshakeTransport(conn keyingTransport, config *Config, clientVersion,
serverVersion: serverVersion,
clientVersion: clientVersion,
incoming: make(chan []byte, chanSize),
- requestKex: make(chan bool, 1),
+ requestKex: make(chan struct{}, 1),
startKex: make(chan *pendingKex, 1),
config: config,
}
// We always start with a mandatory key exchange.
- t.requestKex <- true
+ t.requestKex <- struct{}{}
return t
}
@@ -166,6 +166,7 @@ func (t *handshakeTransport) printPacket(p []byte, write bool) {
if write {
action = "sent"
}
+
if p[0] == msgChannelData || p[0] == msgChannelExtendedData {
log.Printf("%s %s data (packet %d bytes)", t.id(), action, len(p))
} else {
@@ -230,14 +231,13 @@ func (t *handshakeTransport) recordWriteError(err error) {
func (t *handshakeTransport) requestKeyExchange() {
select {
- case t.requestKex <- false:
+ case t.requestKex <- struct{}{}:
default:
// something already requested a kex, so do nothing.
}
}
func (t *handshakeTransport) kexLoop() {
- firstSent := false
write:
for t.getWriteError() == nil {
@@ -251,18 +251,8 @@ write:
if !ok {
break write
}
- case requestFirst := <-t.requestKex:
- // For the first key exchange, both
- // sides will initiate a key exchange,
- // and both channels will fire. To
- // avoid doing two key exchanges in a
- // row, ignore our own request for an
- // initial kex if we have already sent
- // it out.
- if firstSent && requestFirst {
-
- continue
- }
+ case <-t.requestKex:
+ break
}
if !sent {
@@ -270,7 +260,6 @@ write:
t.recordWriteError(err)
break
}
- firstSent = true
sent = true
}
}
@@ -287,7 +276,8 @@ write:
// We're not servicing t.startKex, but the remote end
// has just sent us a kexInitMsg, so it can't send
- // another key change request.
+ // another key change request, until we close the done
+ // channel on the pendingKex request.
err := t.enterKeyExchange(request.otherInit)
@@ -301,6 +291,23 @@ write:
} else if t.algorithms != nil {
t.writeBytesLeft = t.algorithms.w.rekeyBytes()
}
+
+ // we have completed the key exchange. Since the
+ // reader is still blocked, it is safe to clear out
+ // the requestKex channel. This avoids the situation
+ // where: 1) we consumed our own request for the
+ // initial kex, and 2) the kex from the remote side
+ // caused another send on the requestKex channel,
+ clear:
+ for {
+ select {
+ case <-t.requestKex:
+ //
+ default:
+ break clear
+ }
+ }
+
request.done <- t.writeError
// kex finished. Push packets that we received while
@@ -314,7 +321,7 @@ write:
break
}
}
- t.pendingPackets = t.pendingPackets[0:]
+ t.pendingPackets = t.pendingPackets[:0]
t.mu.Unlock()
}
diff --git a/vendor/golang.org/x/crypto/ssh/handshake_test.go b/vendor/golang.org/x/crypto/ssh/handshake_test.go
index e61348fea7..1b831127e8 100644
--- a/vendor/golang.org/x/crypto/ssh/handshake_test.go
+++ b/vendor/golang.org/x/crypto/ssh/handshake_test.go
@@ -40,7 +40,7 @@ func (t *testChecker) Check(dialAddr string, addr net.Addr, key PublicKey) error
// therefore is buffered (net.Pipe deadlocks if both sides start with
// a write.)
func netPipe() (net.Conn, net.Conn, error) {
- listener, err := net.Listen("tcp", "127.0.0.1:0")
+ listener, err := net.Listen("tcp", ":0")
if err != nil {
return nil, nil, err
}
@@ -125,7 +125,12 @@ func TestHandshakeBasic(t *testing.T) {
t.Skip("see golang.org/issue/7237")
}
- checker := &syncChecker{make(chan int, 10)}
+ checker := &syncChecker{
+ waitCall: make(chan int, 10),
+ called: make(chan int, 10),
+ }
+
+ checker.waitCall <- 1
trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr", false)
if err != nil {
t.Fatalf("handshakePair: %v", err)
@@ -134,22 +139,25 @@ func TestHandshakeBasic(t *testing.T) {
defer trC.Close()
defer trS.Close()
+ // Let first kex complete normally.
<-checker.called
clientDone := make(chan int, 0)
gotHalf := make(chan int, 0)
+ const N = 20
go func() {
defer close(clientDone)
// Client writes a bunch of stuff, and does a key
// change in the middle. This should not confuse the
- // handshake in progress
- for i := 0; i < 10; i++ {
+ // handshake in progress. We do this twice, so we test
+ // that the packet buffer is reset correctly.
+ for i := 0; i < N; i++ {
p := []byte{msgRequestSuccess, byte(i)}
if err := trC.writePacket(p); err != nil {
t.Fatalf("sendPacket: %v", err)
}
- if i == 5 {
+ if (i % 10) == 5 {
<-gotHalf
// halfway through, we request a key change.
trC.requestKeyExchange()
@@ -159,32 +167,38 @@ func TestHandshakeBasic(t *testing.T) {
// write more.
<-checker.called
}
+ if (i % 10) == 7 {
+ // write some packets until the kex
+ // completes, to test buffering of
+ // packets.
+ checker.waitCall <- 1
+ }
}
}()
// Server checks that client messages come in cleanly
i := 0
err = nil
- for ; i < 10; i++ {
+ for ; i < N; i++ {
var p []byte
p, err = trS.readPacket()
if err != nil {
break
}
- if i == 5 {
+ if (i % 10) == 5 {
gotHalf <- 1
}
want := []byte{msgRequestSuccess, byte(i)}
if bytes.Compare(p, want) != 0 {
- t.Errorf("message %d: got %q, want %q", i, p, want)
+ t.Errorf("message %d: got %v, want %v", i, p, want)
}
}
<-clientDone
if err != nil && err != io.EOF {
t.Fatalf("server error: %v", err)
}
- if i != 10 {
+ if i != N {
t.Errorf("received %d messages, want 10.", i)
}
@@ -239,7 +253,10 @@ func TestForceFirstKex(t *testing.T) {
}
func TestHandshakeAutoRekeyWrite(t *testing.T) {
- checker := &syncChecker{make(chan int, 10)}
+ checker := &syncChecker{
+ called: make(chan int, 10),
+ waitCall: nil,
+ }
clientConf := &ClientConfig{HostKeyCallback: checker.Check}
clientConf.RekeyThreshold = 500
trC, trS, err := handshakePair(clientConf, "addr", false)
@@ -249,14 +266,19 @@ func TestHandshakeAutoRekeyWrite(t *testing.T) {
defer trC.Close()
defer trS.Close()
+ input := make([]byte, 251)
+ input[0] = msgRequestSuccess
+
done := make(chan int, 1)
const numPacket = 5
go func() {
defer close(done)
j := 0
for ; j < numPacket; j++ {
- if _, err := trS.readPacket(); err != nil {
+ if p, err := trS.readPacket(); err != nil {
break
+ } else if !bytes.Equal(input, p) {
+ t.Errorf("got packet type %d, want %d", p[0], input[0])
}
}
@@ -268,9 +290,9 @@ func TestHandshakeAutoRekeyWrite(t *testing.T) {
<-checker.called
for i := 0; i < numPacket; i++ {
- packet := make([]byte, 251)
- packet[0] = msgRequestSuccess
- if err := trC.writePacket(packet); err != nil {
+ p := make([]byte, len(input))
+ copy(p, input)
+ if err := trC.writePacket(p); err != nil {
t.Errorf("writePacket: %v", err)
}
if i == 2 {
@@ -283,16 +305,23 @@ func TestHandshakeAutoRekeyWrite(t *testing.T) {
}
type syncChecker struct {
- called chan int
+ waitCall chan int
+ called chan int
}
func (c *syncChecker) Check(dialAddr string, addr net.Addr, key PublicKey) error {
c.called <- 1
+ if c.waitCall != nil {
+ <-c.waitCall
+ }
return nil
}
func TestHandshakeAutoRekeyRead(t *testing.T) {
- sync := &syncChecker{make(chan int, 2)}
+ sync := &syncChecker{
+ called: make(chan int, 2),
+ waitCall: nil,
+ }
clientConf := &ClientConfig{
HostKeyCallback: sync.Check,
}
diff --git a/vendor/golang.org/x/crypto/ssh/mac.go b/vendor/golang.org/x/crypto/ssh/mac.go
index 07744ad671..c07a06285e 100644
--- a/vendor/golang.org/x/crypto/ssh/mac.go
+++ b/vendor/golang.org/x/crypto/ssh/mac.go
@@ -15,6 +15,7 @@ import (
type macMode struct {
keySize int
+ etm bool
new func(key []byte) hash.Hash
}
@@ -45,13 +46,16 @@ func (t truncatingMAC) Size() int {
func (t truncatingMAC) BlockSize() int { return t.hmac.BlockSize() }
var macModes = map[string]*macMode{
- "hmac-sha2-256": {32, func(key []byte) hash.Hash {
+ "hmac-sha2-256-etm@openssh.com": {32, true, func(key []byte) hash.Hash {
return hmac.New(sha256.New, key)
}},
- "hmac-sha1": {20, func(key []byte) hash.Hash {
+ "hmac-sha2-256": {32, false, func(key []byte) hash.Hash {
+ return hmac.New(sha256.New, key)
+ }},
+ "hmac-sha1": {20, false, func(key []byte) hash.Hash {
return hmac.New(sha1.New, key)
}},
- "hmac-sha1-96": {20, func(key []byte) hash.Hash {
+ "hmac-sha1-96": {20, false, func(key []byte) hash.Hash {
return truncatingMAC{12, hmac.New(sha1.New, key)}
}},
}
diff --git a/vendor/golang.org/x/crypto/ssh/mux_test.go b/vendor/golang.org/x/crypto/ssh/mux_test.go
index 591aae8e8f..25d2181d62 100644
--- a/vendor/golang.org/x/crypto/ssh/mux_test.go
+++ b/vendor/golang.org/x/crypto/ssh/mux_test.go
@@ -499,4 +499,7 @@ func TestDebug(t *testing.T) {
if debugHandshake {
t.Error("handshake debug switched on")
}
+ if debugTransport {
+ t.Error("transport debug switched on")
+ }
}
diff --git a/vendor/golang.org/x/crypto/ssh/server.go b/vendor/golang.org/x/crypto/ssh/server.go
index 28b109a9c0..77c84d165c 100644
--- a/vendor/golang.org/x/crypto/ssh/server.go
+++ b/vendor/golang.org/x/crypto/ssh/server.go
@@ -10,6 +10,7 @@ import (
"fmt"
"io"
"net"
+ "strings"
)
// The Permissions type holds fine-grained permissions that are
@@ -231,7 +232,7 @@ func isAcceptableAlgo(algo string) bool {
return false
}
-func checkSourceAddress(addr net.Addr, sourceAddr string) error {
+func checkSourceAddress(addr net.Addr, sourceAddrs string) error {
if addr == nil {
return errors.New("ssh: no address known for client, but source-address match required")
}
@@ -241,18 +242,20 @@ func checkSourceAddress(addr net.Addr, sourceAddr string) error {
return fmt.Errorf("ssh: remote address %v is not an TCP address when checking source-address match", addr)
}
- if allowedIP := net.ParseIP(sourceAddr); allowedIP != nil {
- if allowedIP.Equal(tcpAddr.IP) {
- return nil
- }
- } else {
- _, ipNet, err := net.ParseCIDR(sourceAddr)
- if err != nil {
- return fmt.Errorf("ssh: error parsing source-address restriction %q: %v", sourceAddr, err)
- }
+ for _, sourceAddr := range strings.Split(sourceAddrs, ",") {
+ if allowedIP := net.ParseIP(sourceAddr); allowedIP != nil {
+ if allowedIP.Equal(tcpAddr.IP) {
+ return nil
+ }
+ } else {
+ _, ipNet, err := net.ParseCIDR(sourceAddr)
+ if err != nil {
+ return fmt.Errorf("ssh: error parsing source-address restriction %q: %v", sourceAddr, err)
+ }
- if ipNet.Contains(tcpAddr.IP) {
- return nil
+ if ipNet.Contains(tcpAddr.IP) {
+ return nil
+ }
}
}
diff --git a/vendor/golang.org/x/crypto/ssh/transport.go b/vendor/golang.org/x/crypto/ssh/transport.go
index fd199324dd..f9780e0ae7 100644
--- a/vendor/golang.org/x/crypto/ssh/transport.go
+++ b/vendor/golang.org/x/crypto/ssh/transport.go
@@ -8,8 +8,13 @@ import (
"bufio"
"errors"
"io"
+ "log"
)
+// debugTransport if set, will print packet types as they go over the
+// wire. No message decoding is done, to minimize the impact on timing.
+const debugTransport = false
+
const (
gcmCipherID = "aes128-gcm@openssh.com"
aes128cbcID = "aes128-cbc"
@@ -40,7 +45,7 @@ type transport struct {
bufReader *bufio.Reader
bufWriter *bufio.Writer
rand io.Reader
-
+ isClient bool
io.Closer
}
@@ -86,6 +91,22 @@ func (t *transport) prepareKeyChange(algs *algorithms, kexResult *kexResult) err
return nil
}
+func (t *transport) printPacket(p []byte, write bool) {
+ if len(p) == 0 {
+ return
+ }
+ who := "server"
+ if t.isClient {
+ who = "client"
+ }
+ what := "read"
+ if write {
+ what = "write"
+ }
+
+ log.Println(what, who, p[0])
+}
+
// Read and decrypt next packet.
func (t *transport) readPacket() (p []byte, err error) {
for {
@@ -97,6 +118,9 @@ func (t *transport) readPacket() (p []byte, err error) {
break
}
}
+ if debugTransport {
+ t.printPacket(p, false)
+ }
return p, err
}
@@ -141,6 +165,9 @@ func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) {
}
func (t *transport) writePacket(packet []byte) error {
+ if debugTransport {
+ t.printPacket(packet, true)
+ }
return t.writer.writePacket(t.bufWriter, t.rand, packet)
}
@@ -181,6 +208,8 @@ func newTransport(rwc io.ReadWriteCloser, rand io.Reader, isClient bool) *transp
},
Closer: rwc,
}
+ t.isClient = isClient
+
if isClient {
t.reader.dir = serverKeys
t.writer.dir = clientKeys
@@ -238,6 +267,7 @@ func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (pac
c := &streamPacketCipher{
mac: macModes[algs.MAC].new(macKey),
+ etm: macModes[algs.MAC].etm,
}
c.macResult = make([]byte, c.mac.Size())
diff --git a/vendor/golang.org/x/image/draw/draw.go b/vendor/golang.org/x/image/draw/draw.go
index b92e3c7f96..dfaa7fc55e 100644
--- a/vendor/golang.org/x/image/draw/draw.go
+++ b/vendor/golang.org/x/image/draw/draw.go
@@ -11,12 +11,12 @@
// package in the standard library.
package draw
-// This file just contains the API exported by the image/draw package in the
-// standard library. Other files in this package provide additional features.
+// This file, and the go1_*.go files, just contains the API exported by the
+// image/draw package in the standard library. Other files in this package
+// provide additional features.
import (
"image"
- "image/color"
"image/draw"
)
@@ -32,13 +32,6 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas
draw.DrawMask(dst, r, src, sp, mask, mp, draw.Op(op))
}
-// Drawer contains the Draw method.
-type Drawer interface {
- // Draw aligns r.Min in dst with sp in src and then replaces the
- // rectangle r in dst with the result of drawing src on dst.
- Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point)
-}
-
// FloydSteinberg is a Drawer that is the Src Op with Floyd-Steinberg error
// diffusion.
var FloydSteinberg Drawer = floydSteinberg{}
@@ -48,32 +41,3 @@ type floydSteinberg struct{}
func (floydSteinberg) Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point) {
draw.FloydSteinberg.Draw(dst, r, src, sp)
}
-
-// Image is an image.Image with a Set method to change a single pixel.
-type Image interface {
- image.Image
- Set(x, y int, c color.Color)
-}
-
-// Op is a Porter-Duff compositing operator.
-type Op int
-
-const (
- // Over specifies ``(src in mask) over dst''.
- Over Op = Op(draw.Over)
- // Src specifies ``src in mask''.
- Src Op = Op(draw.Src)
-)
-
-// Draw implements the Drawer interface by calling the Draw function with
-// this Op.
-func (op Op) Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point) {
- (draw.Op(op)).Draw(dst, r, src, sp)
-}
-
-// Quantizer produces a palette for an image.
-type Quantizer interface {
- // Quantize appends up to cap(p) - len(p) colors to p and returns the
- // updated palette suitable for converting m to a paletted image.
- Quantize(p color.Palette, m image.Image) color.Palette
-}
diff --git a/vendor/golang.org/x/image/draw/gen.go b/vendor/golang.org/x/image/draw/gen.go
index 0fed47437f..65a7123509 100644
--- a/vendor/golang.org/x/image/draw/gen.go
+++ b/vendor/golang.org/x/image/draw/gen.go
@@ -804,7 +804,7 @@ func cOffset(x, y, sratio string) string {
func ycbcrToRGB(lhs, tmp string) string {
s := `
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- $yy1 := int(src.Y[$i]) * 0x10100
+ $yy1 := int(src.Y[$i]) * 0x10101
$cb1 := int(src.Cb[$j]) - 128
$cr1 := int(src.Cr[$j]) - 128
$r@ := ($yy1 + 91881*$cr1) >> 8
diff --git a/vendor/golang.org/x/image/draw/go1_8.go b/vendor/golang.org/x/image/draw/go1_8.go
new file mode 100644
index 0000000000..ec192b7173
--- /dev/null
+++ b/vendor/golang.org/x/image/draw/go1_8.go
@@ -0,0 +1,49 @@
+// 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 !go1.9,!go1.8.typealias
+
+package draw
+
+import (
+ "image"
+ "image/color"
+ "image/draw"
+)
+
+// Drawer contains the Draw method.
+type Drawer interface {
+ // Draw aligns r.Min in dst with sp in src and then replaces the
+ // rectangle r in dst with the result of drawing src on dst.
+ Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point)
+}
+
+// Image is an image.Image with a Set method to change a single pixel.
+type Image interface {
+ image.Image
+ Set(x, y int, c color.Color)
+}
+
+// Op is a Porter-Duff compositing operator.
+type Op int
+
+const (
+ // Over specifies ``(src in mask) over dst''.
+ Over Op = Op(draw.Over)
+ // Src specifies ``src in mask''.
+ Src Op = Op(draw.Src)
+)
+
+// Draw implements the Drawer interface by calling the Draw function with
+// this Op.
+func (op Op) Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point) {
+ (draw.Op(op)).Draw(dst, r, src, sp)
+}
+
+// Quantizer produces a palette for an image.
+type Quantizer interface {
+ // Quantize appends up to cap(p) - len(p) colors to p and returns the
+ // updated palette suitable for converting m to a paletted image.
+ Quantize(p color.Palette, m image.Image) color.Palette
+}
diff --git a/vendor/golang.org/x/image/draw/go1_9.go b/vendor/golang.org/x/image/draw/go1_9.go
new file mode 100644
index 0000000000..fc548e9470
--- /dev/null
+++ b/vendor/golang.org/x/image/draw/go1_9.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.
+
+// +build go1.9 go1.8.typealias
+
+package draw
+
+import (
+ "image/draw"
+)
+
+// We use type aliases (new in Go 1.9) for the exported names from the standard
+// library's image/draw package. This is not merely syntactic sugar for
+//
+// type Drawer draw.Drawer
+//
+// as aliasing means that the types in this package, such as draw.Image and
+// draw.Op, are identical to the corresponding draw.Image and draw.Op types in
+// the standard library. In comparison, prior to Go 1.9, the code in go1_8.go
+// defines new types that mimic the old but are different types.
+//
+// The package documentation, in draw.go, explicitly gives the intent of this
+// package:
+//
+// This package is a superset of and a drop-in replacement for the
+// image/draw package in the standard library.
+//
+// Drop-in replacement means that I can replace all of my "image/draw" imports
+// with "golang.org/x/image/draw", to access additional features in this
+// package, and no further changes are required. That's mostly true, but not
+// completely true unless we use type aliases.
+//
+// Without type aliases, users might need to import both "image/draw" and
+// "golang.org/x/image/draw" in order to convert from two conceptually
+// equivalent but different (from the compiler's point of view) types, such as
+// from one draw.Op type to another draw.Op type, to satisfy some other
+// interface or function signature.
+
+// Drawer contains the Draw method.
+type Drawer = draw.Drawer
+
+// Image is an image.Image with a Set method to change a single pixel.
+type Image = draw.Image
+
+// Op is a Porter-Duff compositing operator.
+type Op = draw.Op
+
+const (
+ // Over specifies ``(src in mask) over dst''.
+ Over Op = draw.Over
+ // Src specifies ``src in mask''.
+ Src Op = draw.Src
+)
+
+// Quantizer produces a palette for an image.
+type Quantizer = draw.Quantizer
diff --git a/vendor/golang.org/x/image/draw/impl.go b/vendor/golang.org/x/image/draw/impl.go
index d6484d7340..637887be68 100644
--- a/vendor/golang.org/x/image/draw/impl.go
+++ b/vendor/golang.org/x/image/draw/impl.go
@@ -343,7 +343,7 @@ func (nnInterpolator) scale_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Rec
pj := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx) - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10100
+ pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pr := (pyy1 + 91881*pcr1) >> 8
@@ -386,7 +386,7 @@ func (nnInterpolator) scale_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Rec
pj := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx))/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10100
+ pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pr := (pyy1 + 91881*pcr1) >> 8
@@ -429,7 +429,7 @@ func (nnInterpolator) scale_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Rec
pj := ((sr.Min.Y+int(sy))/2-src.Rect.Min.Y/2)*src.CStride + ((sr.Min.X+int(sx))/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10100
+ pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pr := (pyy1 + 91881*pcr1) >> 8
@@ -472,7 +472,7 @@ func (nnInterpolator) scale_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Rec
pj := ((sr.Min.Y+int(sy))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx) - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10100
+ pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pr := (pyy1 + 91881*pcr1) >> 8
@@ -759,7 +759,7 @@ func (nnInterpolator) transform_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image
pj := (sy0-src.Rect.Min.Y)*src.CStride + (sx0 - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10100
+ pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pr := (pyy1 + 91881*pcr1) >> 8
@@ -803,7 +803,7 @@ func (nnInterpolator) transform_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image
pj := (sy0-src.Rect.Min.Y)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10100
+ pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pr := (pyy1 + 91881*pcr1) >> 8
@@ -847,7 +847,7 @@ func (nnInterpolator) transform_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image
pj := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10100
+ pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pr := (pyy1 + 91881*pcr1) >> 8
@@ -891,7 +891,7 @@ func (nnInterpolator) transform_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image
pj := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + (sx0 - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10100
+ pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pr := (pyy1 + 91881*pcr1) >> 8
@@ -1756,7 +1756,7 @@ func (ablInterpolator) scale_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Re
s00j := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s00yy1 := int(src.Y[s00i]) * 0x10100
+ s00yy1 := int(src.Y[s00i]) * 0x10101
s00cb1 := int(src.Cb[s00j]) - 128
s00cr1 := int(src.Cr[s00j]) - 128
s00ru := (s00yy1 + 91881*s00cr1) >> 8
@@ -1785,7 +1785,7 @@ func (ablInterpolator) scale_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Re
s10j := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s10yy1 := int(src.Y[s10i]) * 0x10100
+ s10yy1 := int(src.Y[s10i]) * 0x10101
s10cb1 := int(src.Cb[s10j]) - 128
s10cr1 := int(src.Cr[s10j]) - 128
s10ru := (s10yy1 + 91881*s10cr1) >> 8
@@ -1817,7 +1817,7 @@ func (ablInterpolator) scale_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Re
s01j := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s01yy1 := int(src.Y[s01i]) * 0x10100
+ s01yy1 := int(src.Y[s01i]) * 0x10101
s01cb1 := int(src.Cb[s01j]) - 128
s01cr1 := int(src.Cr[s01j]) - 128
s01ru := (s01yy1 + 91881*s01cr1) >> 8
@@ -1846,7 +1846,7 @@ func (ablInterpolator) scale_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Re
s11j := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s11yy1 := int(src.Y[s11i]) * 0x10100
+ s11yy1 := int(src.Y[s11i]) * 0x10101
s11cb1 := int(src.Cb[s11j]) - 128
s11cr1 := int(src.Cr[s11j]) - 128
s11ru := (s11yy1 + 91881*s11cr1) >> 8
@@ -1931,7 +1931,7 @@ func (ablInterpolator) scale_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Re
s00j := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx0))/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s00yy1 := int(src.Y[s00i]) * 0x10100
+ s00yy1 := int(src.Y[s00i]) * 0x10101
s00cb1 := int(src.Cb[s00j]) - 128
s00cr1 := int(src.Cr[s00j]) - 128
s00ru := (s00yy1 + 91881*s00cr1) >> 8
@@ -1960,7 +1960,7 @@ func (ablInterpolator) scale_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Re
s10j := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx1))/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s10yy1 := int(src.Y[s10i]) * 0x10100
+ s10yy1 := int(src.Y[s10i]) * 0x10101
s10cb1 := int(src.Cb[s10j]) - 128
s10cr1 := int(src.Cr[s10j]) - 128
s10ru := (s10yy1 + 91881*s10cr1) >> 8
@@ -1992,7 +1992,7 @@ func (ablInterpolator) scale_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Re
s01j := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx0))/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s01yy1 := int(src.Y[s01i]) * 0x10100
+ s01yy1 := int(src.Y[s01i]) * 0x10101
s01cb1 := int(src.Cb[s01j]) - 128
s01cr1 := int(src.Cr[s01j]) - 128
s01ru := (s01yy1 + 91881*s01cr1) >> 8
@@ -2021,7 +2021,7 @@ func (ablInterpolator) scale_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Re
s11j := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx1))/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s11yy1 := int(src.Y[s11i]) * 0x10100
+ s11yy1 := int(src.Y[s11i]) * 0x10101
s11cb1 := int(src.Cb[s11j]) - 128
s11cr1 := int(src.Cr[s11j]) - 128
s11ru := (s11yy1 + 91881*s11cr1) >> 8
@@ -2106,7 +2106,7 @@ func (ablInterpolator) scale_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Re
s00j := ((sr.Min.Y+int(sy0))/2-src.Rect.Min.Y/2)*src.CStride + ((sr.Min.X+int(sx0))/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s00yy1 := int(src.Y[s00i]) * 0x10100
+ s00yy1 := int(src.Y[s00i]) * 0x10101
s00cb1 := int(src.Cb[s00j]) - 128
s00cr1 := int(src.Cr[s00j]) - 128
s00ru := (s00yy1 + 91881*s00cr1) >> 8
@@ -2135,7 +2135,7 @@ func (ablInterpolator) scale_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Re
s10j := ((sr.Min.Y+int(sy0))/2-src.Rect.Min.Y/2)*src.CStride + ((sr.Min.X+int(sx1))/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s10yy1 := int(src.Y[s10i]) * 0x10100
+ s10yy1 := int(src.Y[s10i]) * 0x10101
s10cb1 := int(src.Cb[s10j]) - 128
s10cr1 := int(src.Cr[s10j]) - 128
s10ru := (s10yy1 + 91881*s10cr1) >> 8
@@ -2167,7 +2167,7 @@ func (ablInterpolator) scale_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Re
s01j := ((sr.Min.Y+int(sy1))/2-src.Rect.Min.Y/2)*src.CStride + ((sr.Min.X+int(sx0))/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s01yy1 := int(src.Y[s01i]) * 0x10100
+ s01yy1 := int(src.Y[s01i]) * 0x10101
s01cb1 := int(src.Cb[s01j]) - 128
s01cr1 := int(src.Cr[s01j]) - 128
s01ru := (s01yy1 + 91881*s01cr1) >> 8
@@ -2196,7 +2196,7 @@ func (ablInterpolator) scale_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Re
s11j := ((sr.Min.Y+int(sy1))/2-src.Rect.Min.Y/2)*src.CStride + ((sr.Min.X+int(sx1))/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s11yy1 := int(src.Y[s11i]) * 0x10100
+ s11yy1 := int(src.Y[s11i]) * 0x10101
s11cb1 := int(src.Cb[s11j]) - 128
s11cr1 := int(src.Cr[s11j]) - 128
s11ru := (s11yy1 + 91881*s11cr1) >> 8
@@ -2281,7 +2281,7 @@ func (ablInterpolator) scale_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Re
s00j := ((sr.Min.Y+int(sy0))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s00yy1 := int(src.Y[s00i]) * 0x10100
+ s00yy1 := int(src.Y[s00i]) * 0x10101
s00cb1 := int(src.Cb[s00j]) - 128
s00cr1 := int(src.Cr[s00j]) - 128
s00ru := (s00yy1 + 91881*s00cr1) >> 8
@@ -2310,7 +2310,7 @@ func (ablInterpolator) scale_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Re
s10j := ((sr.Min.Y+int(sy0))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s10yy1 := int(src.Y[s10i]) * 0x10100
+ s10yy1 := int(src.Y[s10i]) * 0x10101
s10cb1 := int(src.Cb[s10j]) - 128
s10cr1 := int(src.Cr[s10j]) - 128
s10ru := (s10yy1 + 91881*s10cr1) >> 8
@@ -2342,7 +2342,7 @@ func (ablInterpolator) scale_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Re
s01j := ((sr.Min.Y+int(sy1))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s01yy1 := int(src.Y[s01i]) * 0x10100
+ s01yy1 := int(src.Y[s01i]) * 0x10101
s01cb1 := int(src.Cb[s01j]) - 128
s01cr1 := int(src.Cr[s01j]) - 128
s01ru := (s01yy1 + 91881*s01cr1) >> 8
@@ -2371,7 +2371,7 @@ func (ablInterpolator) scale_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Re
s11j := ((sr.Min.Y+int(sy1))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s11yy1 := int(src.Y[s11i]) * 0x10100
+ s11yy1 := int(src.Y[s11i]) * 0x10101
s11cb1 := int(src.Cb[s11j]) - 128
s11cr1 := int(src.Cr[s11j]) - 128
s11ru := (s11yy1 + 91881*s11cr1) >> 8
@@ -3345,7 +3345,7 @@ func (ablInterpolator) transform_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr imag
s00j := (sy0-src.Rect.Min.Y)*src.CStride + (sx0 - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s00yy1 := int(src.Y[s00i]) * 0x10100
+ s00yy1 := int(src.Y[s00i]) * 0x10101
s00cb1 := int(src.Cb[s00j]) - 128
s00cr1 := int(src.Cr[s00j]) - 128
s00ru := (s00yy1 + 91881*s00cr1) >> 8
@@ -3374,7 +3374,7 @@ func (ablInterpolator) transform_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr imag
s10j := (sy0-src.Rect.Min.Y)*src.CStride + (sx1 - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s10yy1 := int(src.Y[s10i]) * 0x10100
+ s10yy1 := int(src.Y[s10i]) * 0x10101
s10cb1 := int(src.Cb[s10j]) - 128
s10cr1 := int(src.Cr[s10j]) - 128
s10ru := (s10yy1 + 91881*s10cr1) >> 8
@@ -3406,7 +3406,7 @@ func (ablInterpolator) transform_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr imag
s01j := (sy1-src.Rect.Min.Y)*src.CStride + (sx0 - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s01yy1 := int(src.Y[s01i]) * 0x10100
+ s01yy1 := int(src.Y[s01i]) * 0x10101
s01cb1 := int(src.Cb[s01j]) - 128
s01cr1 := int(src.Cr[s01j]) - 128
s01ru := (s01yy1 + 91881*s01cr1) >> 8
@@ -3435,7 +3435,7 @@ func (ablInterpolator) transform_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr imag
s11j := (sy1-src.Rect.Min.Y)*src.CStride + (sx1 - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s11yy1 := int(src.Y[s11i]) * 0x10100
+ s11yy1 := int(src.Y[s11i]) * 0x10101
s11cb1 := int(src.Cb[s11j]) - 128
s11cr1 := int(src.Cr[s11j]) - 128
s11ru := (s11yy1 + 91881*s11cr1) >> 8
@@ -3521,7 +3521,7 @@ func (ablInterpolator) transform_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr imag
s00j := (sy0-src.Rect.Min.Y)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s00yy1 := int(src.Y[s00i]) * 0x10100
+ s00yy1 := int(src.Y[s00i]) * 0x10101
s00cb1 := int(src.Cb[s00j]) - 128
s00cr1 := int(src.Cr[s00j]) - 128
s00ru := (s00yy1 + 91881*s00cr1) >> 8
@@ -3550,7 +3550,7 @@ func (ablInterpolator) transform_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr imag
s10j := (sy0-src.Rect.Min.Y)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s10yy1 := int(src.Y[s10i]) * 0x10100
+ s10yy1 := int(src.Y[s10i]) * 0x10101
s10cb1 := int(src.Cb[s10j]) - 128
s10cr1 := int(src.Cr[s10j]) - 128
s10ru := (s10yy1 + 91881*s10cr1) >> 8
@@ -3582,7 +3582,7 @@ func (ablInterpolator) transform_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr imag
s01j := (sy1-src.Rect.Min.Y)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s01yy1 := int(src.Y[s01i]) * 0x10100
+ s01yy1 := int(src.Y[s01i]) * 0x10101
s01cb1 := int(src.Cb[s01j]) - 128
s01cr1 := int(src.Cr[s01j]) - 128
s01ru := (s01yy1 + 91881*s01cr1) >> 8
@@ -3611,7 +3611,7 @@ func (ablInterpolator) transform_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr imag
s11j := (sy1-src.Rect.Min.Y)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s11yy1 := int(src.Y[s11i]) * 0x10100
+ s11yy1 := int(src.Y[s11i]) * 0x10101
s11cb1 := int(src.Cb[s11j]) - 128
s11cr1 := int(src.Cr[s11j]) - 128
s11ru := (s11yy1 + 91881*s11cr1) >> 8
@@ -3697,7 +3697,7 @@ func (ablInterpolator) transform_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr imag
s00j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s00yy1 := int(src.Y[s00i]) * 0x10100
+ s00yy1 := int(src.Y[s00i]) * 0x10101
s00cb1 := int(src.Cb[s00j]) - 128
s00cr1 := int(src.Cr[s00j]) - 128
s00ru := (s00yy1 + 91881*s00cr1) >> 8
@@ -3726,7 +3726,7 @@ func (ablInterpolator) transform_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr imag
s10j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s10yy1 := int(src.Y[s10i]) * 0x10100
+ s10yy1 := int(src.Y[s10i]) * 0x10101
s10cb1 := int(src.Cb[s10j]) - 128
s10cr1 := int(src.Cr[s10j]) - 128
s10ru := (s10yy1 + 91881*s10cr1) >> 8
@@ -3758,7 +3758,7 @@ func (ablInterpolator) transform_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr imag
s01j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s01yy1 := int(src.Y[s01i]) * 0x10100
+ s01yy1 := int(src.Y[s01i]) * 0x10101
s01cb1 := int(src.Cb[s01j]) - 128
s01cr1 := int(src.Cr[s01j]) - 128
s01ru := (s01yy1 + 91881*s01cr1) >> 8
@@ -3787,7 +3787,7 @@ func (ablInterpolator) transform_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr imag
s11j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s11yy1 := int(src.Y[s11i]) * 0x10100
+ s11yy1 := int(src.Y[s11i]) * 0x10101
s11cb1 := int(src.Cb[s11j]) - 128
s11cr1 := int(src.Cr[s11j]) - 128
s11ru := (s11yy1 + 91881*s11cr1) >> 8
@@ -3873,7 +3873,7 @@ func (ablInterpolator) transform_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr imag
s00j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + (sx0 - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s00yy1 := int(src.Y[s00i]) * 0x10100
+ s00yy1 := int(src.Y[s00i]) * 0x10101
s00cb1 := int(src.Cb[s00j]) - 128
s00cr1 := int(src.Cr[s00j]) - 128
s00ru := (s00yy1 + 91881*s00cr1) >> 8
@@ -3902,7 +3902,7 @@ func (ablInterpolator) transform_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr imag
s10j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + (sx1 - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s10yy1 := int(src.Y[s10i]) * 0x10100
+ s10yy1 := int(src.Y[s10i]) * 0x10101
s10cb1 := int(src.Cb[s10j]) - 128
s10cr1 := int(src.Cr[s10j]) - 128
s10ru := (s10yy1 + 91881*s10cr1) >> 8
@@ -3934,7 +3934,7 @@ func (ablInterpolator) transform_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr imag
s01j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + (sx0 - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s01yy1 := int(src.Y[s01i]) * 0x10100
+ s01yy1 := int(src.Y[s01i]) * 0x10101
s01cb1 := int(src.Cb[s01j]) - 128
s01cr1 := int(src.Cr[s01j]) - 128
s01ru := (s01yy1 + 91881*s01cr1) >> 8
@@ -3963,7 +3963,7 @@ func (ablInterpolator) transform_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr imag
s11j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + (sx1 - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s11yy1 := int(src.Y[s11i]) * 0x10100
+ s11yy1 := int(src.Y[s11i]) * 0x10101
s11cb1 := int(src.Cb[s11j]) - 128
s11cr1 := int(src.Cr[s11j]) - 128
s11ru := (s11yy1 + 91881*s11cr1) >> 8
@@ -4729,7 +4729,7 @@ func (z *kernelScaler) scaleX_YCbCr444(tmp [][4]float64, src *image.YCbCr, sr im
pj := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10100
+ pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pru := (pyy1 + 91881*pcr1) >> 8
@@ -4776,7 +4776,7 @@ func (z *kernelScaler) scaleX_YCbCr422(tmp [][4]float64, src *image.YCbCr, sr im
pj := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(c.coord))/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10100
+ pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pru := (pyy1 + 91881*pcr1) >> 8
@@ -4823,7 +4823,7 @@ func (z *kernelScaler) scaleX_YCbCr420(tmp [][4]float64, src *image.YCbCr, sr im
pj := ((sr.Min.Y+int(y))/2-src.Rect.Min.Y/2)*src.CStride + ((sr.Min.X+int(c.coord))/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10100
+ pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pru := (pyy1 + 91881*pcr1) >> 8
@@ -4870,7 +4870,7 @@ func (z *kernelScaler) scaleX_YCbCr440(tmp [][4]float64, src *image.YCbCr, sr im
pj := ((sr.Min.Y+int(y))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10100
+ pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pru := (pyy1 + 91881*pcr1) >> 8
@@ -5759,7 +5759,7 @@ func (q *Kernel) transform_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Rect
pj := (ky-src.Rect.Min.Y)*src.CStride + (kx - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10100
+ pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pru := (pyy1 + 91881*pcr1) >> 8
@@ -5883,7 +5883,7 @@ func (q *Kernel) transform_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Rect
pj := (ky-src.Rect.Min.Y)*src.CStride + ((kx)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10100
+ pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pru := (pyy1 + 91881*pcr1) >> 8
@@ -6007,7 +6007,7 @@ func (q *Kernel) transform_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Rect
pj := ((ky)/2-src.Rect.Min.Y/2)*src.CStride + ((kx)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10100
+ pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pru := (pyy1 + 91881*pcr1) >> 8
@@ -6131,7 +6131,7 @@ func (q *Kernel) transform_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Rect
pj := ((ky)/2-src.Rect.Min.Y/2)*src.CStride + (kx - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10100
+ pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pru := (pyy1 + 91881*pcr1) >> 8
diff --git a/vendor/golang.org/x/image/draw/stdlib_test.go b/vendor/golang.org/x/image/draw/stdlib_test.go
index c45f78c2e4..9015bfd6ff 100644
--- a/vendor/golang.org/x/image/draw/stdlib_test.go
+++ b/vendor/golang.org/x/image/draw/stdlib_test.go
@@ -2,14 +2,14 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build go1.5
+// +build go1.9
package draw
// This file contains tests that depend on the exact behavior of the
// image/color package in the standard library. The color conversion formula
-// from YCbCr to RGBA changed between Go 1.4 and Go 1.5, so this file's tests
-// are only enabled for Go 1.5 and above.
+// from YCbCr to RGBA changed between Go 1.4 and Go 1.5, and between Go 1.8 and
+// Go 1.9, so this file's tests are only enabled for Go 1.9 and above.
import (
"bytes"
diff --git a/vendor/golang.org/x/image/font/sfnt/cmap.go b/vendor/golang.org/x/image/font/sfnt/cmap.go
new file mode 100644
index 0000000000..42338f1bc6
--- /dev/null
+++ b/vendor/golang.org/x/image/font/sfnt/cmap.go
@@ -0,0 +1,269 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sfnt
+
+import (
+ "unicode/utf8"
+
+ "golang.org/x/text/encoding/charmap"
+)
+
+// Platform IDs and Platform Specific IDs as per
+// https://www.microsoft.com/typography/otspec/name.htm
+const (
+ pidUnicode = 0
+ pidMacintosh = 1
+ pidWindows = 3
+
+ psidUnicode2BMPOnly = 3
+ psidUnicode2FullRepertoire = 4
+ // Note that FontForge may generate a bogus Platform Specific ID (value 10)
+ // for the Unicode Platform ID (value 0). See
+ // https://github.com/fontforge/fontforge/issues/2728
+
+ psidMacintoshRoman = 0
+
+ psidWindowsSymbol = 0
+ psidWindowsUCS2 = 1
+ psidWindowsUCS4 = 10
+)
+
+// platformEncodingWidth returns the number of bytes per character assumed by
+// the given Platform ID and Platform Specific ID.
+//
+// Very old fonts, from before Unicode was widely adopted, assume only 1 byte
+// per character: a character map.
+//
+// Old fonts, from when Unicode meant the Basic Multilingual Plane (BMP),
+// assume that 2 bytes per character is sufficient.
+//
+// Recent fonts naturally support the full range of Unicode code points, which
+// can take up to 4 bytes per character. Such fonts might still choose one of
+// the legacy encodings if e.g. their repertoire is limited to the BMP, for
+// greater compatibility with older software, or because the resultant file
+// size can be smaller.
+func platformEncodingWidth(pid, psid uint16) int {
+ switch pid {
+ case pidUnicode:
+ switch psid {
+ case psidUnicode2BMPOnly:
+ return 2
+ case psidUnicode2FullRepertoire:
+ return 4
+ }
+
+ case pidMacintosh:
+ switch psid {
+ case psidMacintoshRoman:
+ return 1
+ }
+
+ case pidWindows:
+ switch psid {
+ case psidWindowsSymbol:
+ return 2
+ case psidWindowsUCS2:
+ return 2
+ case psidWindowsUCS4:
+ return 4
+ }
+ }
+ return 0
+}
+
+// The various cmap formats are described at
+// https://www.microsoft.com/typography/otspec/cmap.htm
+
+var supportedCmapFormat = func(format, pid, psid uint16) bool {
+ switch format {
+ case 0:
+ return pid == pidMacintosh && psid == psidMacintoshRoman
+ case 4:
+ return true
+ case 12:
+ return true
+ }
+ return false
+}
+
+func (f *Font) makeCachedGlyphIndex(buf []byte, offset, length uint32, format uint16) ([]byte, glyphIndexFunc, error) {
+ switch format {
+ case 0:
+ return f.makeCachedGlyphIndexFormat0(buf, offset, length)
+ case 4:
+ return f.makeCachedGlyphIndexFormat4(buf, offset, length)
+ case 12:
+ return f.makeCachedGlyphIndexFormat12(buf, offset, length)
+ }
+ panic("unreachable")
+}
+
+func (f *Font) makeCachedGlyphIndexFormat0(buf []byte, offset, length uint32) ([]byte, glyphIndexFunc, error) {
+ if length != 6+256 || offset+length > f.cmap.length {
+ return nil, nil, errInvalidCmapTable
+ }
+ var err error
+ buf, err = f.src.view(buf, int(f.cmap.offset+offset), int(length))
+ if err != nil {
+ return nil, nil, err
+ }
+ var table [256]byte
+ copy(table[:], buf[6:])
+ return buf, func(f *Font, b *Buffer, r rune) (GlyphIndex, error) {
+ // TODO: for this closure to be goroutine-safe, the
+ // golang.org/x/text/encoding/charmap API needs to allocate a new
+ // Encoder and new []byte buffers, for every call to this closure, even
+ // though all we want to do is to encode one rune as one byte. We could
+ // possibly add some fields in the Buffer struct to re-use these
+ // allocations, but a better solution is to improve the charmap API.
+ var dst, src [utf8.UTFMax]byte
+ n := utf8.EncodeRune(src[:], r)
+ _, _, err = charmap.Macintosh.NewEncoder().Transform(dst[:], src[:n], true)
+ if err != nil {
+ // The source rune r is not representable in the Macintosh-Roman encoding.
+ return 0, nil
+ }
+ return GlyphIndex(table[dst[0]]), nil
+ }, nil
+}
+
+func (f *Font) makeCachedGlyphIndexFormat4(buf []byte, offset, length uint32) ([]byte, glyphIndexFunc, error) {
+ const headerSize = 14
+ if offset+headerSize > f.cmap.length {
+ return nil, nil, errInvalidCmapTable
+ }
+ var err error
+ buf, err = f.src.view(buf, int(f.cmap.offset+offset), headerSize)
+ if err != nil {
+ return nil, nil, err
+ }
+ offset += headerSize
+
+ segCount := u16(buf[6:])
+ if segCount&1 != 0 {
+ return nil, nil, errInvalidCmapTable
+ }
+ segCount /= 2
+ if segCount > maxCmapSegments {
+ return nil, nil, errUnsupportedNumberOfCmapSegments
+ }
+
+ eLength := 8*uint32(segCount) + 2
+ if offset+eLength > f.cmap.length {
+ return nil, nil, errInvalidCmapTable
+ }
+ buf, err = f.src.view(buf, int(f.cmap.offset+offset), int(eLength))
+ if err != nil {
+ return nil, nil, err
+ }
+ offset += eLength
+
+ entries := make([]cmapEntry16, segCount)
+ for i := range entries {
+ entries[i] = cmapEntry16{
+ end: u16(buf[0*len(entries)+0+2*i:]),
+ start: u16(buf[2*len(entries)+2+2*i:]),
+ delta: u16(buf[4*len(entries)+2+2*i:]),
+ offset: u16(buf[6*len(entries)+2+2*i:]),
+ }
+ }
+ indexesBase := f.cmap.offset + offset
+ indexesLength := f.cmap.length - offset
+
+ return buf, func(f *Font, b *Buffer, r rune) (GlyphIndex, error) {
+ if uint32(r) > 0xffff {
+ return 0, nil
+ }
+
+ c := uint16(r)
+ for i, j := 0, len(entries); i < j; {
+ h := i + (j-i)/2
+ entry := &entries[h]
+ if c < entry.start {
+ j = h
+ } else if entry.end < c {
+ i = h + 1
+ } else if entry.offset == 0 {
+ return GlyphIndex(c + entry.delta), nil
+ } else {
+ offset := uint32(entry.offset) + 2*uint32(h-len(entries)+int(c-entry.start))
+ if offset > indexesLength || offset+2 > indexesLength {
+ return 0, errInvalidCmapTable
+ }
+ x, err := b.view(&f.src, int(indexesBase+offset), 2)
+ if err != nil {
+ return 0, err
+ }
+ return GlyphIndex(u16(x)), nil
+ }
+ }
+ return 0, nil
+ }, nil
+}
+
+func (f *Font) makeCachedGlyphIndexFormat12(buf []byte, offset, _ uint32) ([]byte, glyphIndexFunc, error) {
+ const headerSize = 16
+ if offset+headerSize > f.cmap.length {
+ return nil, nil, errInvalidCmapTable
+ }
+ var err error
+ buf, err = f.src.view(buf, int(f.cmap.offset+offset), headerSize)
+ if err != nil {
+ return nil, nil, err
+ }
+ length := u32(buf[4:])
+ if f.cmap.length < offset || length > f.cmap.length-offset {
+ return nil, nil, errInvalidCmapTable
+ }
+ offset += headerSize
+
+ numGroups := u32(buf[12:])
+ if numGroups > maxCmapSegments {
+ return nil, nil, errUnsupportedNumberOfCmapSegments
+ }
+
+ eLength := 12 * numGroups
+ if headerSize+eLength != length {
+ return nil, nil, errInvalidCmapTable
+ }
+ buf, err = f.src.view(buf, int(f.cmap.offset+offset), int(eLength))
+ if err != nil {
+ return nil, nil, err
+ }
+ offset += eLength
+
+ entries := make([]cmapEntry32, numGroups)
+ for i := range entries {
+ entries[i] = cmapEntry32{
+ start: u32(buf[0+12*i:]),
+ end: u32(buf[4+12*i:]),
+ delta: u32(buf[8+12*i:]),
+ }
+ }
+
+ return buf, func(f *Font, b *Buffer, r rune) (GlyphIndex, error) {
+ c := uint32(r)
+ for i, j := 0, len(entries); i < j; {
+ h := i + (j-i)/2
+ entry := &entries[h]
+ if c < entry.start {
+ j = h
+ } else if entry.end < c {
+ i = h + 1
+ } else {
+ return GlyphIndex(c - entry.start + entry.delta), nil
+ }
+ }
+ return 0, nil
+ }, nil
+}
+
+type cmapEntry16 struct {
+ end, start, delta, offset uint16
+}
+
+type cmapEntry32 struct {
+ start, end, delta uint32
+}
diff --git a/vendor/golang.org/x/image/font/sfnt/data.go b/vendor/golang.org/x/image/font/sfnt/data.go
new file mode 100644
index 0000000000..ad0c139aa8
--- /dev/null
+++ b/vendor/golang.org/x/image/font/sfnt/data.go
@@ -0,0 +1,68 @@
+// generated by go run gen.go; DO NOT EDIT
+
+package sfnt
+
+const numBuiltInPostNames = 258
+
+const builtInPostNamesData = "" +
+ ".notdef.nullnonmarkingreturnspaceexclamquotedblnumbersigndollarp" +
+ "ercentampersandquotesingleparenleftparenrightasteriskpluscommahy" +
+ "phenperiodslashzeroonetwothreefourfivesixseveneightninecolonsemi" +
+ "colonlessequalgreaterquestionatABCDEFGHIJKLMNOPQRSTUVWXYZbracket" +
+ "leftbackslashbracketrightasciicircumunderscoregraveabcdefghijklm" +
+ "nopqrstuvwxyzbraceleftbarbracerightasciitildeAdieresisAringCcedi" +
+ "llaEacuteNtildeOdieresisUdieresisaacuteagraveacircumflexadieresi" +
+ "satildearingccedillaeacuteegraveecircumflexedieresisiacuteigrave" +
+ "icircumflexidieresisntildeoacuteograveocircumflexodieresisotilde" +
+ "uacuteugraveucircumflexudieresisdaggerdegreecentsterlingsectionb" +
+ "ulletparagraphgermandblsregisteredcopyrighttrademarkacutedieresi" +
+ "snotequalAEOslashinfinityplusminuslessequalgreaterequalyenmupart" +
+ "ialdiffsummationproductpiintegralordfeminineordmasculineOmegaaeo" +
+ "slashquestiondownexclamdownlogicalnotradicalflorinapproxequalDel" +
+ "taguillemotleftguillemotrightellipsisnonbreakingspaceAgraveAtild" +
+ "eOtildeOEoeendashemdashquotedblleftquotedblrightquoteleftquoteri" +
+ "ghtdividelozengeydieresisYdieresisfractioncurrencyguilsinglleftg" +
+ "uilsinglrightfifldaggerdblperiodcenteredquotesinglbasequotedblba" +
+ "seperthousandAcircumflexEcircumflexAacuteEdieresisEgraveIacuteIc" +
+ "ircumflexIdieresisIgraveOacuteOcircumflexappleOgraveUacuteUcircu" +
+ "mflexUgravedotlessicircumflextildemacronbrevedotaccentringcedill" +
+ "ahungarumlautogonekcaronLslashlslashScaronscaronZcaronzcaronbrok" +
+ "enbarEthethYacuteyacuteThornthornminusmultiplyonesuperiortwosupe" +
+ "riorthreesuperioronehalfonequarterthreequartersfrancGbrevegbreve" +
+ "IdotaccentScedillascedillaCacutecacuteCcaronccarondcroat"
+
+var builtInPostNamesOffsets = [...]uint16{
+ 0x0000, 0x0007, 0x000c, 0x001c, 0x0021, 0x0027, 0x002f, 0x0039,
+ 0x003f, 0x0046, 0x004f, 0x005a, 0x0063, 0x006d, 0x0075, 0x0079,
+ 0x007e, 0x0084, 0x008a, 0x008f, 0x0093, 0x0096, 0x0099, 0x009e,
+ 0x00a2, 0x00a6, 0x00a9, 0x00ae, 0x00b3, 0x00b7, 0x00bc, 0x00c5,
+ 0x00c9, 0x00ce, 0x00d5, 0x00dd, 0x00df, 0x00e0, 0x00e1, 0x00e2,
+ 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea,
+ 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, 0x00f0, 0x00f1, 0x00f2,
+ 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x0104,
+ 0x010d, 0x0119, 0x0124, 0x012e, 0x0133, 0x0134, 0x0135, 0x0136,
+ 0x0137, 0x0138, 0x0139, 0x013a, 0x013b, 0x013c, 0x013d, 0x013e,
+ 0x013f, 0x0140, 0x0141, 0x0142, 0x0143, 0x0144, 0x0145, 0x0146,
+ 0x0147, 0x0148, 0x0149, 0x014a, 0x014b, 0x014c, 0x014d, 0x0156,
+ 0x0159, 0x0163, 0x016d, 0x0176, 0x017b, 0x0183, 0x0189, 0x018f,
+ 0x0198, 0x01a1, 0x01a7, 0x01ad, 0x01b8, 0x01c1, 0x01c7, 0x01cc,
+ 0x01d4, 0x01da, 0x01e0, 0x01eb, 0x01f4, 0x01fa, 0x0200, 0x020b,
+ 0x0214, 0x021a, 0x0220, 0x0226, 0x0231, 0x023a, 0x0240, 0x0246,
+ 0x024c, 0x0257, 0x0260, 0x0266, 0x026c, 0x0270, 0x0278, 0x027f,
+ 0x0285, 0x028e, 0x0298, 0x02a2, 0x02ab, 0x02b4, 0x02b9, 0x02c1,
+ 0x02c9, 0x02cb, 0x02d1, 0x02d9, 0x02e2, 0x02eb, 0x02f7, 0x02fa,
+ 0x02fc, 0x0307, 0x0310, 0x0317, 0x0319, 0x0321, 0x032c, 0x0338,
+ 0x033d, 0x033f, 0x0345, 0x0351, 0x035b, 0x0365, 0x036c, 0x0372,
+ 0x037d, 0x0382, 0x038f, 0x039d, 0x03a5, 0x03b5, 0x03bb, 0x03c1,
+ 0x03c7, 0x03c9, 0x03cb, 0x03d1, 0x03d7, 0x03e3, 0x03f0, 0x03f9,
+ 0x0403, 0x0409, 0x0410, 0x0419, 0x0422, 0x042a, 0x0432, 0x043f,
+ 0x044d, 0x044f, 0x0451, 0x045a, 0x0468, 0x0476, 0x0482, 0x048d,
+ 0x0498, 0x04a3, 0x04a9, 0x04b2, 0x04b8, 0x04be, 0x04c9, 0x04d2,
+ 0x04d8, 0x04de, 0x04e9, 0x04ee, 0x04f4, 0x04fa, 0x0505, 0x050b,
+ 0x0513, 0x051d, 0x0522, 0x0528, 0x052d, 0x0536, 0x053a, 0x0541,
+ 0x054d, 0x0553, 0x0558, 0x055e, 0x0564, 0x056a, 0x0570, 0x0576,
+ 0x057c, 0x0585, 0x0588, 0x058b, 0x0591, 0x0597, 0x059c, 0x05a1,
+ 0x05a6, 0x05ae, 0x05b9, 0x05c4, 0x05d1, 0x05d8, 0x05e2, 0x05ef,
+ 0x05f4, 0x05fa, 0x0600, 0x060a, 0x0612, 0x061a, 0x0620, 0x0626,
+ 0x062c, 0x0632, 0x0638,
+}
diff --git a/vendor/golang.org/x/image/font/sfnt/example_test.go b/vendor/golang.org/x/image/font/sfnt/example_test.go
new file mode 100644
index 0000000000..17431560fc
--- /dev/null
+++ b/vendor/golang.org/x/image/font/sfnt/example_test.go
@@ -0,0 +1,128 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sfnt_test
+
+import (
+ "image"
+ "image/draw"
+ "log"
+ "os"
+
+ "golang.org/x/image/font/gofont/goregular"
+ "golang.org/x/image/font/sfnt"
+ "golang.org/x/image/math/fixed"
+ "golang.org/x/image/vector"
+)
+
+func ExampleRasterizeGlyph() {
+ const (
+ ppem = 32
+ width = 24
+ height = 32
+ originX = 0
+ originY = 28
+ )
+
+ f, err := sfnt.Parse(goregular.TTF)
+ if err != nil {
+ log.Fatalf("Parse: %v", err)
+ }
+ var b sfnt.Buffer
+ x, err := f.GlyphIndex(&b, 'G')
+ if err != nil {
+ log.Fatalf("GlyphIndex: %v", err)
+ }
+ if x == 0 {
+ log.Fatalf("GlyphIndex: no glyph index found for the rune 'G'")
+ }
+ segments, err := f.LoadGlyph(&b, x, fixed.I(ppem), nil)
+ if err != nil {
+ log.Fatalf("LoadGlyph: %v", err)
+ }
+
+ r := vector.NewRasterizer(width, height)
+ r.DrawOp = draw.Src
+ for _, seg := range segments {
+ // The divisions by 64 below is because the seg.Args values have type
+ // fixed.Int26_6, a 26.6 fixed point number, and 1<<6 == 64.
+ switch seg.Op {
+ case sfnt.SegmentOpMoveTo:
+ r.MoveTo(
+ originX+float32(seg.Args[0])/64,
+ originY-float32(seg.Args[1])/64,
+ )
+ case sfnt.SegmentOpLineTo:
+ r.LineTo(
+ originX+float32(seg.Args[0])/64,
+ originY-float32(seg.Args[1])/64,
+ )
+ case sfnt.SegmentOpQuadTo:
+ r.QuadTo(
+ originX+float32(seg.Args[0])/64,
+ originY-float32(seg.Args[1])/64,
+ originX+float32(seg.Args[2])/64,
+ originY-float32(seg.Args[3])/64,
+ )
+ case sfnt.SegmentOpCubeTo:
+ r.CubeTo(
+ originX+float32(seg.Args[0])/64,
+ originY-float32(seg.Args[1])/64,
+ originX+float32(seg.Args[2])/64,
+ originY-float32(seg.Args[3])/64,
+ originX+float32(seg.Args[4])/64,
+ originY-float32(seg.Args[5])/64,
+ )
+ }
+ }
+ // TODO: call ClosePath? Once overall or once per contour (i.e. MoveTo)?
+
+ dst := image.NewAlpha(image.Rect(0, 0, width, height))
+ r.Draw(dst, dst.Bounds(), image.Opaque, image.Point{})
+
+ const asciiArt = ".++8"
+ buf := make([]byte, 0, height*(width+1))
+ for y := 0; y < height; y++ {
+ for x := 0; x < width; x++ {
+ a := dst.AlphaAt(x, y).A
+ buf = append(buf, asciiArt[a>>6])
+ }
+ buf = append(buf, '\n')
+ }
+ os.Stdout.Write(buf)
+
+ // Output:
+ // ........................
+ // ........................
+ // ........................
+ // ........................
+ // ..........+++++++++.....
+ // .......+8888888888888+..
+ // ......8888888888888888..
+ // ....+8888+........++88..
+ // ....8888................
+ // ...8888.................
+ // ..+888+.................
+ // ..+888..................
+ // ..888+..................
+ // .+888+..................
+ // .+888...................
+ // .+888...................
+ // .+888...................
+ // .+888..........+++++++..
+ // .+888..........8888888..
+ // .+888+.........+++8888..
+ // ..888+............+888..
+ // ..8888............+888..
+ // ..+888+...........+888..
+ // ...8888+..........+888..
+ // ...+8888+.........+888..
+ // ....+88888+.......+888..
+ // .....+8888888888888888..
+ // .......+888888888888++..
+ // ..........++++++++......
+ // ........................
+ // ........................
+ // ........................
+}
diff --git a/vendor/golang.org/x/image/font/sfnt/gen.go b/vendor/golang.org/x/image/font/sfnt/gen.go
new file mode 100644
index 0000000000..12587d4460
--- /dev/null
+++ b/vendor/golang.org/x/image/font/sfnt/gen.go
@@ -0,0 +1,321 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "go/format"
+ "io/ioutil"
+ "log"
+)
+
+func main() {
+ data, offsets := []byte(nil), []int{0}
+ for _, name := range names {
+ data = append(data, name...)
+ offsets = append(offsets, len(data))
+ }
+
+ b := new(bytes.Buffer)
+ fmt.Fprintf(b, "// generated by go run gen.go; DO NOT EDIT\n\n")
+ fmt.Fprintf(b, "package sfnt\n\n")
+
+ fmt.Fprintf(b, "const numBuiltInPostNames = %d\n\n", len(names))
+
+ fmt.Fprintf(b, "const builtInPostNamesData = \"\" +\n")
+ for s := data; ; {
+ if len(s) <= 64 {
+ fmt.Fprintf(b, "%q\n", s)
+ break
+ }
+ fmt.Fprintf(b, "%q +\n", s[:64])
+ s = s[64:]
+ }
+ fmt.Fprintf(b, "\n")
+
+ fmt.Fprintf(b, "var builtInPostNamesOffsets = [...]uint16{\n")
+ for i, o := range offsets {
+ fmt.Fprintf(b, "%#04x,", o)
+ if i%8 == 7 {
+ fmt.Fprintf(b, "\n")
+ }
+ }
+ fmt.Fprintf(b, "\n}\n")
+
+ dstUnformatted := b.Bytes()
+ dst, err := format.Source(dstUnformatted)
+ if err != nil {
+ log.Fatalf("format.Source: %v\n\n----\n%s\n----", err, dstUnformatted)
+ }
+ if err := ioutil.WriteFile("data.go", dst, 0666); err != nil {
+ log.Fatalf("ioutil.WriteFile: %v", err)
+ }
+}
+
+// names is the built-in post table names listed at
+// https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6post.html
+var names = [258]string{
+ ".notdef",
+ ".null",
+ "nonmarkingreturn",
+ "space",
+ "exclam",
+ "quotedbl",
+ "numbersign",
+ "dollar",
+ "percent",
+ "ampersand",
+ "quotesingle",
+ "parenleft",
+ "parenright",
+ "asterisk",
+ "plus",
+ "comma",
+ "hyphen",
+ "period",
+ "slash",
+ "zero",
+ "one",
+ "two",
+ "three",
+ "four",
+ "five",
+ "six",
+ "seven",
+ "eight",
+ "nine",
+ "colon",
+ "semicolon",
+ "less",
+ "equal",
+ "greater",
+ "question",
+ "at",
+ "A",
+ "B",
+ "C",
+ "D",
+ "E",
+ "F",
+ "G",
+ "H",
+ "I",
+ "J",
+ "K",
+ "L",
+ "M",
+ "N",
+ "O",
+ "P",
+ "Q",
+ "R",
+ "S",
+ "T",
+ "U",
+ "V",
+ "W",
+ "X",
+ "Y",
+ "Z",
+ "bracketleft",
+ "backslash",
+ "bracketright",
+ "asciicircum",
+ "underscore",
+ "grave",
+ "a",
+ "b",
+ "c",
+ "d",
+ "e",
+ "f",
+ "g",
+ "h",
+ "i",
+ "j",
+ "k",
+ "l",
+ "m",
+ "n",
+ "o",
+ "p",
+ "q",
+ "r",
+ "s",
+ "t",
+ "u",
+ "v",
+ "w",
+ "x",
+ "y",
+ "z",
+ "braceleft",
+ "bar",
+ "braceright",
+ "asciitilde",
+ "Adieresis",
+ "Aring",
+ "Ccedilla",
+ "Eacute",
+ "Ntilde",
+ "Odieresis",
+ "Udieresis",
+ "aacute",
+ "agrave",
+ "acircumflex",
+ "adieresis",
+ "atilde",
+ "aring",
+ "ccedilla",
+ "eacute",
+ "egrave",
+ "ecircumflex",
+ "edieresis",
+ "iacute",
+ "igrave",
+ "icircumflex",
+ "idieresis",
+ "ntilde",
+ "oacute",
+ "ograve",
+ "ocircumflex",
+ "odieresis",
+ "otilde",
+ "uacute",
+ "ugrave",
+ "ucircumflex",
+ "udieresis",
+ "dagger",
+ "degree",
+ "cent",
+ "sterling",
+ "section",
+ "bullet",
+ "paragraph",
+ "germandbls",
+ "registered",
+ "copyright",
+ "trademark",
+ "acute",
+ "dieresis",
+ "notequal",
+ "AE",
+ "Oslash",
+ "infinity",
+ "plusminus",
+ "lessequal",
+ "greaterequal",
+ "yen",
+ "mu",
+ "partialdiff",
+ "summation",
+ "product",
+ "pi",
+ "integral",
+ "ordfeminine",
+ "ordmasculine",
+ "Omega",
+ "ae",
+ "oslash",
+ "questiondown",
+ "exclamdown",
+ "logicalnot",
+ "radical",
+ "florin",
+ "approxequal",
+ "Delta",
+ "guillemotleft",
+ "guillemotright",
+ "ellipsis",
+ "nonbreakingspace",
+ "Agrave",
+ "Atilde",
+ "Otilde",
+ "OE",
+ "oe",
+ "endash",
+ "emdash",
+ "quotedblleft",
+ "quotedblright",
+ "quoteleft",
+ "quoteright",
+ "divide",
+ "lozenge",
+ "ydieresis",
+ "Ydieresis",
+ "fraction",
+ "currency",
+ "guilsinglleft",
+ "guilsinglright",
+ "fi",
+ "fl",
+ "daggerdbl",
+ "periodcentered",
+ "quotesinglbase",
+ "quotedblbase",
+ "perthousand",
+ "Acircumflex",
+ "Ecircumflex",
+ "Aacute",
+ "Edieresis",
+ "Egrave",
+ "Iacute",
+ "Icircumflex",
+ "Idieresis",
+ "Igrave",
+ "Oacute",
+ "Ocircumflex",
+ "apple",
+ "Ograve",
+ "Uacute",
+ "Ucircumflex",
+ "Ugrave",
+ "dotlessi",
+ "circumflex",
+ "tilde",
+ "macron",
+ "breve",
+ "dotaccent",
+ "ring",
+ "cedilla",
+ "hungarumlaut",
+ "ogonek",
+ "caron",
+ "Lslash",
+ "lslash",
+ "Scaron",
+ "scaron",
+ "Zcaron",
+ "zcaron",
+ "brokenbar",
+ "Eth",
+ "eth",
+ "Yacute",
+ "yacute",
+ "Thorn",
+ "thorn",
+ "minus",
+ "multiply",
+ "onesuperior",
+ "twosuperior",
+ "threesuperior",
+ "onehalf",
+ "onequarter",
+ "threequarters",
+ "franc",
+ "Gbreve",
+ "gbreve",
+ "Idotaccent",
+ "Scedilla",
+ "scedilla",
+ "Cacute",
+ "cacute",
+ "Ccaron",
+ "ccaron",
+ "dcroat",
+}
diff --git a/vendor/golang.org/x/image/font/sfnt/postscript.go b/vendor/golang.org/x/image/font/sfnt/postscript.go
index d5d6d9aed9..ca1b8318ce 100644
--- a/vendor/golang.org/x/image/font/sfnt/postscript.go
+++ b/vendor/golang.org/x/image/font/sfnt/postscript.go
@@ -566,8 +566,8 @@ var psOperators = [...][2][]psOperator{
23: {-1, "vstemhm", t2CStem},
24: {}, // rcurveline.
25: {}, // rlinecurve.
- 26: {}, // vvcurveto.
- 27: {}, // hhcurveto.
+ 26: {-1, "vvcurveto", t2CVvcurveto},
+ 27: {-1, "hhcurveto", t2CHhcurveto},
28: {}, // shortint.
29: {}, // callgsubr.
30: {-1, "vhcurveto", t2CVhcurveto},
@@ -653,8 +653,8 @@ func t2CAppendMoveto(p *psInterpreter) {
p.type2Charstrings.segments = append(p.type2Charstrings.segments, Segment{
Op: SegmentOpMoveTo,
Args: [6]fixed.Int26_6{
- 0: fixed.Int26_6(p.type2Charstrings.x) << 6,
- 1: fixed.Int26_6(p.type2Charstrings.y) << 6,
+ 0: fixed.Int26_6(p.type2Charstrings.x),
+ 1: fixed.Int26_6(p.type2Charstrings.y),
},
})
}
@@ -663,8 +663,8 @@ func t2CAppendLineto(p *psInterpreter) {
p.type2Charstrings.segments = append(p.type2Charstrings.segments, Segment{
Op: SegmentOpLineTo,
Args: [6]fixed.Int26_6{
- 0: fixed.Int26_6(p.type2Charstrings.x) << 6,
- 1: fixed.Int26_6(p.type2Charstrings.y) << 6,
+ 0: fixed.Int26_6(p.type2Charstrings.x),
+ 1: fixed.Int26_6(p.type2Charstrings.y),
},
})
}
@@ -685,12 +685,12 @@ func t2CAppendCubeto(p *psInterpreter, dxa, dya, dxb, dyb, dxc, dyc int32) {
p.type2Charstrings.segments = append(p.type2Charstrings.segments, Segment{
Op: SegmentOpCubeTo,
Args: [6]fixed.Int26_6{
- 0: fixed.Int26_6(xa) << 6,
- 1: fixed.Int26_6(ya) << 6,
- 2: fixed.Int26_6(xb) << 6,
- 3: fixed.Int26_6(yb) << 6,
- 4: fixed.Int26_6(xc) << 6,
- 5: fixed.Int26_6(yc) << 6,
+ 0: fixed.Int26_6(xa),
+ 1: fixed.Int26_6(ya),
+ 2: fixed.Int26_6(xb),
+ 3: fixed.Int26_6(yb),
+ 4: fixed.Int26_6(xc),
+ 5: fixed.Int26_6(yc),
},
})
}
@@ -770,6 +770,12 @@ func t2CRlineto(p *psInterpreter) error {
// As per 5177.Type2.pdf section 4.1 "Path Construction Operators",
//
+// hhcurveto is:
+// - dy1 {dxa dxb dyb dxc}+
+//
+// vvcurveto is:
+// - dx1 {dya dxb dyb dyc}+
+//
// hvcurveto is one of:
// - dx1 dx2 dy2 dy3 {dya dxb dyb dxc dxd dxe dye dyf}* dxf?
// - {dxa dxb dyb dyc dyd dxe dye dxf}+ dyf?
@@ -778,59 +784,84 @@ func t2CRlineto(p *psInterpreter) error {
// - dy1 dx2 dy2 dx3 {dxa dxb dyb dyc dyd dxe dye dxf}* dyf?
// - {dya dxb dyb dxc dxd dxe dye dyf}+ dxf?
-func t2CHvcurveto(p *psInterpreter) error { return t2CCurveto(p, false) }
-func t2CVhcurveto(p *psInterpreter) error { return t2CCurveto(p, true) }
+func t2CHhcurveto(p *psInterpreter) error { return t2CCurveto(p, false, false) }
+func t2CVvcurveto(p *psInterpreter) error { return t2CCurveto(p, false, true) }
+func t2CHvcurveto(p *psInterpreter) error { return t2CCurveto(p, true, false) }
+func t2CVhcurveto(p *psInterpreter) error { return t2CCurveto(p, true, true) }
-func t2CCurveto(p *psInterpreter, vertical bool) error {
+// t2CCurveto implements the hh / vv / hv / vh xxcurveto operators. N relative
+// cubic curve requires 6*N control points, but only 4*N+0 or 4*N+1 are used
+// here: all (or all but one) of the piecewise cubic curve's tangents are
+// implicitly horizontal or vertical.
+//
+// swap is whether that implicit horizontal / vertical constraint swaps as you
+// move along the piecewise cubic curve. If swap is false, the constraints are
+// either all horizontal or all vertical. If swap is true, it alternates.
+//
+// vertical is whether the first implicit constraint is vertical.
+func t2CCurveto(p *psInterpreter, swap, vertical bool) error {
if !p.type2Charstrings.seenWidth || p.stack.top < 4 {
return errInvalidCFFTable
}
- for i := int32(0); i != p.stack.top; vertical = !vertical {
- if vertical {
- i = t2CVcurveto(p, i)
- } else {
- i = t2CHcurveto(p, i)
+
+ i := int32(0)
+ switch p.stack.top & 3 {
+ case 0:
+ // No-op.
+ case 1:
+ if swap {
+ break
}
+ i = 1
+ if vertical {
+ p.type2Charstrings.x += p.stack.a[0]
+ } else {
+ p.type2Charstrings.y += p.stack.a[0]
+ }
+ default:
+ return errInvalidCFFTable
+ }
+
+ for i != p.stack.top {
+ i = t2CCurveto4(p, swap, vertical, i)
if i < 0 {
return errInvalidCFFTable
}
+ if swap {
+ vertical = !vertical
+ }
}
return nil
}
-func t2CHcurveto(p *psInterpreter, i int32) (j int32) {
+func t2CCurveto4(p *psInterpreter, swap bool, vertical bool, i int32) (j int32) {
if i+4 > p.stack.top {
return -1
}
dxa := p.stack.a[i+0]
- dxb := p.stack.a[i+1]
- dyb := p.stack.a[i+2]
- dyc := p.stack.a[i+3]
- dxc := int32(0)
- i += 4
- if i+1 == p.stack.top {
- dxc = p.stack.a[i]
- i++
- }
- t2CAppendCubeto(p, dxa, 0, dxb, dyb, dxc, dyc)
- return i
-}
-
-func t2CVcurveto(p *psInterpreter, i int32) (j int32) {
- if i+4 > p.stack.top {
- return -1
- }
- dya := p.stack.a[i+0]
+ dya := int32(0)
dxb := p.stack.a[i+1]
dyb := p.stack.a[i+2]
dxc := p.stack.a[i+3]
dyc := int32(0)
i += 4
- if i+1 == p.stack.top {
- dyc = p.stack.a[i]
- i++
+
+ if vertical {
+ dxa, dya = dya, dxa
}
- t2CAppendCubeto(p, 0, dya, dxb, dyb, dxc, dyc)
+
+ if swap {
+ if i+1 == p.stack.top {
+ dyc = p.stack.a[i]
+ i++
+ }
+ }
+
+ if swap != vertical {
+ dxc, dyc = dyc, dxc
+ }
+
+ t2CAppendCubeto(p, dxa, dya, dxb, dyb, dxc, dyc)
return i
}
diff --git a/vendor/golang.org/x/image/font/sfnt/proprietary_test.go b/vendor/golang.org/x/image/font/sfnt/proprietary_test.go
new file mode 100644
index 0000000000..b105ee5933
--- /dev/null
+++ b/vendor/golang.org/x/image/font/sfnt/proprietary_test.go
@@ -0,0 +1,479 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sfnt
+
+/*
+This file contains opt-in tests for popular, high quality, proprietary fonts,
+made by companies such as Adobe and Microsoft. These fonts are generally
+available, but copies are not explicitly included in this repository due to
+licensing differences or file size concerns. To opt-in, run:
+
+go test golang.org/x/image/font/sfnt -args -proprietary
+
+Not all tests pass out-of-the-box on all systems. For example, the Microsoft
+Times New Roman font is downloadable gratis even on non-Windows systems, but as
+per the ttf-mscorefonts-installer Debian package, this requires accepting an
+End User License Agreement (EULA) and a CAB format decoder. These tests assume
+that such fonts have already been installed. You may need to specify the
+directories for these fonts:
+
+go test golang.org/x/image/font/sfnt -args -proprietary -adobeDir=/foo/bar/aFonts -microsoftDir=/foo/bar/mFonts
+
+To only run those tests for the Microsoft fonts:
+
+go test golang.org/x/image/font/sfnt -test.run=ProprietaryMicrosoft -args -proprietary
+*/
+
+// TODO: add Apple system fonts? Google fonts (Droid? Noto?)? Emoji fonts?
+
+// TODO: enable Apple/Microsoft tests by default on Darwin/Windows?
+
+import (
+ "errors"
+ "flag"
+ "io/ioutil"
+ "path/filepath"
+ "testing"
+
+ "golang.org/x/image/font"
+ "golang.org/x/image/math/fixed"
+)
+
+var (
+ proprietary = flag.Bool("proprietary", false, "test proprietary fonts not included in this repository")
+
+ adobeDir = flag.String(
+ "adobeDir",
+ // This needs to be set explicitly. There is no default dir on Debian:
+ // https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=736680
+ //
+ // Get the fonts from https://github.com/adobe-fonts, e.g.:
+ // - https://github.com/adobe-fonts/source-code-pro/releases/latest
+ // - https://github.com/adobe-fonts/source-han-sans/releases/latest
+ // - https://github.com/adobe-fonts/source-sans-pro/releases/latest
+ //
+ // Copy all of the TTF and OTF files to the one directory, such as
+ // $HOME/adobe-fonts, and pass that as the -adobeDir flag here.
+ "",
+ "directory name for the Adobe proprietary fonts",
+ )
+
+ microsoftDir = flag.String(
+ "microsoftDir",
+ "/usr/share/fonts/truetype/msttcorefonts",
+ "directory name for the Microsoft proprietary fonts",
+ )
+)
+
+func TestProprietaryAdobeSourceCodeProOTF(t *testing.T) {
+ testProprietary(t, "adobe", "SourceCodePro-Regular.otf", 1500, 2)
+}
+
+func TestProprietaryAdobeSourceCodeProTTF(t *testing.T) {
+ testProprietary(t, "adobe", "SourceCodePro-Regular.ttf", 1500, 36)
+}
+
+func TestProprietaryAdobeSourceHanSansSC(t *testing.T) {
+ testProprietary(t, "adobe", "SourceHanSansSC-Regular.otf", 65535, 2)
+}
+
+func TestProprietaryAdobeSourceSansProOTF(t *testing.T) {
+ testProprietary(t, "adobe", "SourceSansPro-Regular.otf", 1800, 2)
+}
+
+func TestProprietaryAdobeSourceSansProTTF(t *testing.T) {
+ testProprietary(t, "adobe", "SourceSansPro-Regular.ttf", 1800, 54)
+}
+
+func TestProprietaryMicrosoftArial(t *testing.T) {
+ testProprietary(t, "microsoft", "Arial.ttf", 1200, 98)
+}
+
+func TestProprietaryMicrosoftComicSansMS(t *testing.T) {
+ testProprietary(t, "microsoft", "Comic_Sans_MS.ttf", 550, 98)
+}
+
+func TestProprietaryMicrosoftTimesNewRoman(t *testing.T) {
+ testProprietary(t, "microsoft", "Times_New_Roman.ttf", 1200, 98)
+}
+
+func TestProprietaryMicrosoftWebdings(t *testing.T) {
+ testProprietary(t, "microsoft", "Webdings.ttf", 200, -1)
+}
+
+// testProprietary tests that we can load every glyph in the named font.
+//
+// The exact number of glyphs in the font can differ across its various
+// versions, but as a sanity check, there should be at least minNumGlyphs.
+//
+// While this package is a work-in-progress, not every glyph can be loaded. The
+// firstUnsupportedGlyph argument, if non-negative, is the index of the first
+// unsupported glyph in the font. This number should increase over time (or set
+// negative), as the TODO's in this package are done.
+func testProprietary(t *testing.T, proprietor, filename string, minNumGlyphs, firstUnsupportedGlyph int) {
+ if !*proprietary {
+ t.Skip("skipping proprietary font test")
+ }
+
+ file, err := []byte(nil), error(nil)
+ switch proprietor {
+ case "adobe":
+ file, err = ioutil.ReadFile(filepath.Join(*adobeDir, filename))
+ if err != nil {
+ t.Fatalf("%v\nPerhaps you need to set the -adobeDir=%v flag?", err, *adobeDir)
+ }
+ case "microsoft":
+ file, err = ioutil.ReadFile(filepath.Join(*microsoftDir, filename))
+ if err != nil {
+ t.Fatalf("%v\nPerhaps you need to set the -microsoftDir=%v flag?", err, *microsoftDir)
+ }
+ default:
+ panic("unreachable")
+ }
+ f, err := Parse(file)
+ if err != nil {
+ t.Fatalf("Parse: %v", err)
+ }
+ ppem := fixed.Int26_6(f.UnitsPerEm())
+ qualifiedFilename := proprietor + "/" + filename
+ var buf Buffer
+
+ // Some of the tests below, such as which glyph index a particular rune
+ // maps to, can depend on the specific version of the proprietary font. If
+ // tested against a different version of that font, the test might (but not
+ // necessarily will) fail, even though the Go code is good. If so, log a
+ // message, but don't automatically fail (i.e. dont' call t.Fatalf).
+ gotVersion, err := f.Name(&buf, NameIDVersion)
+ if err != nil {
+ t.Fatalf("Name: %v", err)
+ }
+ wantVersion := proprietaryVersions[qualifiedFilename]
+ if gotVersion != wantVersion {
+ t.Logf("font version provided differs from the one the tests were written against:"+
+ "\ngot %q\nwant %q", gotVersion, wantVersion)
+ }
+
+ numGlyphs := f.NumGlyphs()
+ if numGlyphs < minNumGlyphs {
+ t.Fatalf("NumGlyphs: got %d, want at least %d", numGlyphs, minNumGlyphs)
+ }
+
+ iMax := numGlyphs
+ if firstUnsupportedGlyph >= 0 {
+ iMax = firstUnsupportedGlyph
+ }
+ for i, numErrors := 0, 0; i < iMax; i++ {
+ if _, err := f.LoadGlyph(&buf, GlyphIndex(i), ppem, nil); err != nil {
+ t.Errorf("LoadGlyph(%d): %v", i, err)
+ numErrors++
+ }
+ if numErrors == 10 {
+ t.Fatal("LoadGlyph: too many errors")
+ }
+ }
+
+ for r, want := range proprietaryGlyphIndexTestCases[qualifiedFilename] {
+ got, err := f.GlyphIndex(&buf, r)
+ if err != nil {
+ t.Errorf("GlyphIndex(%q): %v", r, err)
+ continue
+ }
+ if got != want {
+ t.Errorf("GlyphIndex(%q): got %d, want %d", r, got, want)
+ continue
+ }
+ }
+
+ for r, want := range proprietaryGlyphTestCases[qualifiedFilename] {
+ x, err := f.GlyphIndex(&buf, r)
+ if err != nil {
+ t.Errorf("GlyphIndex(%q): %v", r, err)
+ continue
+ }
+ got, err := f.LoadGlyph(&buf, x, ppem, nil)
+ if err != nil {
+ t.Errorf("LoadGlyph(%q): %v", r, err)
+ continue
+ }
+ if err := checkSegmentsEqual(got, want); err != nil {
+ t.Errorf("LoadGlyph(%q): %v", r, err)
+ continue
+ }
+ }
+
+kernLoop:
+ for _, tc := range proprietaryKernTestCases[qualifiedFilename] {
+ var indexes [2]GlyphIndex
+ for i := range indexes {
+ x, err := f.GlyphIndex(&buf, tc.runes[i])
+ if x == 0 && err == nil {
+ err = errors.New("no glyph index found")
+ }
+ if err != nil {
+ t.Errorf("GlyphIndex(%q): %v", tc.runes[0], err)
+ continue kernLoop
+ }
+ indexes[i] = x
+ }
+ kern, err := f.Kern(&buf, indexes[0], indexes[1], tc.ppem, tc.hinting)
+ if err != nil {
+ t.Errorf("Kern(%q, %q, ppem=%d, hinting=%v): %v",
+ tc.runes[0], tc.runes[1], tc.ppem, tc.hinting, err)
+ continue
+ }
+ if got := Units(kern); got != tc.want {
+ t.Errorf("Kern(%q, %q, ppem=%d, hinting=%v): got %d, want %d",
+ tc.runes[0], tc.runes[1], tc.ppem, tc.hinting, got, tc.want)
+ continue
+ }
+ }
+}
+
+// proprietaryVersions holds the expected version string of each proprietary
+// font tested. If third parties such as Adobe or Microsoft update their fonts,
+// and the tests subsequently fail, these versions should be updated too.
+//
+// Updates are expected to be infrequent. For example, as of 2017, the fonts
+// installed by the Debian ttf-mscorefonts-installer package have last modified
+// times no later than 2001.
+var proprietaryVersions = map[string]string{
+ "adobe/SourceCodePro-Regular.otf": "Version 2.030;PS 1.0;hotconv 16.6.51;makeotf.lib2.5.65220",
+ "adobe/SourceCodePro-Regular.ttf": "Version 2.030;PS 1.000;hotconv 16.6.51;makeotf.lib2.5.65220",
+ "adobe/SourceHanSansSC-Regular.otf": "Version 1.004;PS 1.004;hotconv 1.0.82;makeotf.lib2.5.63406",
+ "adobe/SourceSansPro-Regular.otf": "Version 2.020;PS 2.0;hotconv 1.0.86;makeotf.lib2.5.63406",
+ "adobe/SourceSansPro-Regular.ttf": "Version 2.020;PS 2.000;hotconv 1.0.86;makeotf.lib2.5.63406",
+
+ "microsoft/Arial.ttf": "Version 2.82",
+ "microsoft/Comic_Sans_MS.ttf": "Version 2.10",
+ "microsoft/Times_New_Roman.ttf": "Version 2.82",
+ "microsoft/Webdings.ttf": "Version 1.03",
+}
+
+// proprietaryGlyphIndexTestCases hold a sample of each font's rune to glyph
+// index cmap. The numerical values can be verified by running the ttx tool.
+var proprietaryGlyphIndexTestCases = map[string]map[rune]GlyphIndex{
+ "adobe/SourceCodePro-Regular.otf": {
+ '\u0030': 877, // U+0030 DIGIT ZERO
+ '\u0041': 2, // U+0041 LATIN CAPITAL LETTER A
+ '\u0061': 28, // U+0061 LATIN SMALL LETTER A
+ '\u0104': 64, // U+0104 LATIN CAPITAL LETTER A WITH OGONEK
+ '\u0125': 323, // U+0125 LATIN SMALL LETTER H WITH CIRCUMFLEX
+ '\u01f4': 111, // U+01F4 LATIN CAPITAL LETTER G WITH ACUTE
+ '\u03a3': 623, // U+03A3 GREEK CAPITAL LETTER SIGMA
+ '\u2569': 1500, // U+2569 BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+ '\U0001f100': 0, // U+0001F100 DIGIT ZERO FULL STOP
+ },
+ "adobe/SourceCodePro-Regular.ttf": {
+ '\u0030': 877, // U+0030 DIGIT ZERO
+ '\u0041': 2, // U+0041 LATIN CAPITAL LETTER A
+ '\u01f4': 111, // U+01F4 LATIN CAPITAL LETTER G WITH ACUTE
+ },
+ "adobe/SourceHanSansSC-Regular.otf": {
+ '\u0030': 17, // U+0030 DIGIT ZERO
+ '\u0041': 34, // U+0041 LATIN CAPITAL LETTER A
+ '\u00d7': 150, // U+00D7 MULTIPLICATION SIGN
+ '\u1100': 365, // U+1100 HANGUL CHOSEONG KIYEOK
+ '\u25ca': 1254, // U+25CA LOZENGE
+ '\u2e9c': 1359, // U+2E9C CJK RADICAL SUN
+ '\u304b': 1463, // U+304B HIRAGANA LETTER KA
+ '\u4e2d': 9893, // U+4E2D , 中
+ '\ua960': 47537, // U+A960 HANGUL CHOSEONG TIKEUT-MIEUM
+ '\ufb00': 58919, // U+FB00 LATIN SMALL LIGATURE FF
+ '\uffee': 59213, // U+FFEE HALFWIDTH WHITE CIRCLE
+ '\U0001f100': 59214, // U+0001F100 DIGIT ZERO FULL STOP
+ '\U0001f248': 59449, // U+0001F248 TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6557
+ '\U0002f9f4': 61768, // U+0002F9F4 CJK COMPATIBILITY IDEOGRAPH-2F9F4
+ },
+ "adobe/SourceSansPro-Regular.otf": {
+ '\u0041': 2, // U+0041 LATIN CAPITAL LETTER A
+ '\u03a3': 592, // U+03A3 GREEK CAPITAL LETTER SIGMA
+ '\u0435': 999, // U+0435 CYRILLIC SMALL LETTER IE
+ '\u2030': 1728, // U+2030 PER MILLE SIGN
+ },
+ "adobe/SourceSansPro-Regular.ttf": {
+ '\u0041': 2, // U+0041 LATIN CAPITAL LETTER A
+ '\u03a3': 592, // U+03A3 GREEK CAPITAL LETTER SIGMA
+ '\u0435': 999, // U+0435 CYRILLIC SMALL LETTER IE
+ '\u2030': 1728, // U+2030 PER MILLE SIGN
+ },
+
+ "microsoft/Arial.ttf": {
+ '\u0041': 36, // U+0041 LATIN CAPITAL LETTER A
+ '\u00f1': 120, // U+00F1 LATIN SMALL LETTER N WITH TILDE
+ '\u0401': 556, // U+0401 CYRILLIC CAPITAL LETTER IO
+ '\u200d': 745, // U+200D ZERO WIDTH JOINER
+ '\u20ab': 1150, // U+20AB DONG SIGN
+ '\u2229': 320, // U+2229 INTERSECTION
+ '\u04e9': 1319, // U+04E9 CYRILLIC SMALL LETTER BARRED O
+ '\U0001f100': 0, // U+0001F100 DIGIT ZERO FULL STOP
+ },
+ "microsoft/Comic_Sans_MS.ttf": {
+ '\u0041': 36, // U+0041 LATIN CAPITAL LETTER A
+ '\u03af': 573, // U+03AF GREEK SMALL LETTER IOTA WITH TONOS
+ },
+ "microsoft/Times_New_Roman.ttf": {
+ '\u0041': 36, // U+0041 LATIN CAPITAL LETTER A
+ '\u0042': 37, // U+0041 LATIN CAPITAL LETTER B
+ '\u266a': 392, // U+266A EIGHTH NOTE
+ '\uf041': 0, // PRIVATE USE AREA
+ '\uf042': 0, // PRIVATE USE AREA
+ },
+ "microsoft/Webdings.ttf": {
+ '\u0041': 0, // U+0041 LATIN CAPITAL LETTER A
+ '\u0042': 0, // U+0041 LATIN CAPITAL LETTER B
+ '\u266a': 0, // U+266A EIGHTH NOTE
+ '\uf041': 36, // PRIVATE USE AREA
+ '\uf042': 37, // PRIVATE USE AREA
+ },
+}
+
+// proprietaryGlyphTestCases hold a sample of each font's glyph vectors. The
+// numerical values can be verified by running the ttx tool, remembering that:
+// - for PostScript glyphs, ttx coordinates are relative, and hstem / vstem
+// operators are hinting-related and can be ignored.
+// - for TrueType glyphs, ttx coordinates are absolute, and consecutive
+// off-curve points implies an on-curve point at the midpoint.
+var proprietaryGlyphTestCases = map[string]map[rune][]Segment{
+ "adobe/SourceSansPro-Regular.otf": {
+ ',': {
+ // - contour #0
+ // 67 -170 rmoveto
+ moveTo(67, -170),
+ // 81 34 50 67 86 vvcurveto
+ cubeTo(148, -136, 198, -69, 198, 17),
+ // 60 -26 37 -43 -33 -28 -22 -36 -37 27 -20 32 3 4 0 1 3 vhcurveto
+ cubeTo(198, 77, 172, 114, 129, 114),
+ cubeTo(96, 114, 68, 92, 68, 56),
+ cubeTo(68, 19, 95, -1, 127, -1),
+ cubeTo(130, -1, 134, -1, 137, 0),
+ // 1 -53 -34 -44 -57 -25 rrcurveto
+ cubeTo(138, -53, 104, -97, 47, -122),
+ },
+ 'Q': {
+ // - contour #0
+ // 332 57 rmoveto
+ moveTo(332, 57),
+ // -117 -77 106 168 163 77 101 117 117 77 -101 -163 -168 -77 -106 -117 hvcurveto
+ cubeTo(215, 57, 138, 163, 138, 331),
+ cubeTo(138, 494, 215, 595, 332, 595),
+ cubeTo(449, 595, 526, 494, 526, 331),
+ cubeTo(526, 163, 449, 57, 332, 57),
+ // - contour #1
+ // 201 -222 rmoveto
+ moveTo(533, -165),
+ // 39 35 7 8 20 hvcurveto
+ cubeTo(572, -165, 607, -158, 627, -150),
+ // -16 64 rlineto
+ lineTo(611, -86),
+ // -5 -18 -22 -4 -29 hhcurveto
+ cubeTo(593, -91, 571, -95, 542, -95),
+ // -71 -60 29 58 -30 hvcurveto
+ cubeTo(471, -95, 411, -66, 381, -8),
+ // 139 24 93 126 189 vvcurveto
+ cubeTo(520, 16, 613, 142, 613, 331),
+ // 209 -116 128 -165 -165 -115 -127 -210 -193 96 -127 143 -20 vhcurveto
+ cubeTo(613, 540, 497, 668, 332, 668),
+ cubeTo(167, 668, 52, 541, 52, 331),
+ cubeTo(52, 138, 148, 11, 291, -9),
+ // -90 38 83 -66 121 hhcurveto
+ cubeTo(329, -99, 412, -165, 533, -165),
+ },
+ },
+
+ "microsoft/Arial.ttf": {
+ ',': {
+ // - contour #0
+ moveTo(182, 0),
+ lineTo(182, 205),
+ lineTo(387, 205),
+ lineTo(387, 0),
+ quadTo(387, -113, 347, -182),
+ quadTo(307, -252, 220, -290),
+ lineTo(170, -213),
+ quadTo(227, -188, 254, -139),
+ quadTo(281, -91, 284, 0),
+ lineTo(182, 0),
+ },
+ 'i': {
+ // - contour #0
+ moveTo(136, 1259),
+ lineTo(136, 1466),
+ lineTo(316, 1466),
+ lineTo(316, 1259),
+ lineTo(136, 1259),
+ // - contour #1
+ moveTo(136, 0),
+ lineTo(136, 1062),
+ lineTo(316, 1062),
+ lineTo(316, 0),
+ lineTo(136, 0),
+ },
+ 'o': {
+ // - contour #0
+ moveTo(68, 531),
+ quadTo(68, 826, 232, 968),
+ quadTo(369, 1086, 566, 1086),
+ quadTo(785, 1086, 924, 942),
+ quadTo(1063, 799, 1063, 546),
+ quadTo(1063, 341, 1001, 223),
+ quadTo(940, 106, 822, 41),
+ quadTo(705, -24, 566, -24),
+ quadTo(343, -24, 205, 119),
+ quadTo(68, 262, 68, 531),
+ // - contour #1
+ moveTo(253, 531),
+ quadTo(253, 327, 342, 225),
+ quadTo(431, 124, 566, 124),
+ quadTo(700, 124, 789, 226),
+ quadTo(878, 328, 878, 537),
+ quadTo(878, 734, 788, 835),
+ quadTo(699, 937, 566, 937),
+ quadTo(431, 937, 342, 836),
+ quadTo(253, 735, 253, 531),
+ },
+ },
+}
+
+type kernTestCase struct {
+ ppem fixed.Int26_6
+ hinting font.Hinting
+ runes [2]rune
+ want Units
+}
+
+// proprietaryKernTestCases hold a sample of each font's kerning pairs. The
+// numerical values can be verified by running the ttx tool.
+var proprietaryKernTestCases = map[string][]kernTestCase{
+ "microsoft/Arial.ttf": {
+ {2048, font.HintingNone, [2]rune{'A', 'V'}, -152},
+ // U+03B8 GREEK SMALL LETTER THETA
+ // U+03BB GREEK SMALL LETTER LAMDA
+ {2048, font.HintingNone, [2]rune{'\u03b8', '\u03bb'}, -39},
+ {2048, font.HintingNone, [2]rune{'\u03bb', '\u03b8'}, -0},
+ },
+ "microsoft/Comic_Sans_MS.ttf": {
+ {2048, font.HintingNone, [2]rune{'A', 'V'}, 0},
+ },
+ "microsoft/Times_New_Roman.ttf": {
+ {768, font.HintingNone, [2]rune{'A', 'V'}, -99},
+ {768, font.HintingFull, [2]rune{'A', 'V'}, -128},
+ {2048, font.HintingNone, [2]rune{'A', 'A'}, 0},
+ {2048, font.HintingNone, [2]rune{'A', 'T'}, -227},
+ {2048, font.HintingNone, [2]rune{'A', 'V'}, -264},
+ {2048, font.HintingNone, [2]rune{'T', 'A'}, -164},
+ {2048, font.HintingNone, [2]rune{'T', 'T'}, 0},
+ {2048, font.HintingNone, [2]rune{'T', 'V'}, 0},
+ {2048, font.HintingNone, [2]rune{'V', 'A'}, -264},
+ {2048, font.HintingNone, [2]rune{'V', 'T'}, 0},
+ {2048, font.HintingNone, [2]rune{'V', 'V'}, 0},
+ // U+0390 GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
+ // U+0393 GREEK CAPITAL LETTER GAMMA
+ {2048, font.HintingNone, [2]rune{'\u0390', '\u0393'}, 0},
+ {2048, font.HintingNone, [2]rune{'\u0393', '\u0390'}, 76},
+ },
+ "microsoft/Webdings.ttf": {
+ {2048, font.HintingNone, [2]rune{'\uf041', '\uf042'}, 0},
+ },
+}
diff --git a/vendor/golang.org/x/image/font/sfnt/sfnt.go b/vendor/golang.org/x/image/font/sfnt/sfnt.go
index d4929a8381..02efd5f3a5 100644
--- a/vendor/golang.org/x/image/font/sfnt/sfnt.go
+++ b/vendor/golang.org/x/image/font/sfnt/sfnt.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+//go:generate go run gen.go
+
// Package sfnt implements a decoder for SFNT font file formats, including
// TrueType and OpenType.
package sfnt // import "golang.org/x/image/font/sfnt"
@@ -13,11 +15,15 @@ package sfnt // import "golang.org/x/image/font/sfnt"
//
// The pyftinspect tool from https://github.com/fonttools/fonttools is useful
// for inspecting SFNT fonts.
+//
+// The ttfdump tool is also useful. For example:
+// ttfdump -t cmap ../testdata/CFFTest.otf dump.txt
import (
"errors"
"io"
+ "golang.org/x/image/font"
"golang.org/x/image/math/fixed"
"golang.org/x/text/encoding/charmap"
)
@@ -25,6 +31,20 @@ import (
// These constants are not part of the specifications, but are limitations used
// by this implementation.
const (
+ // This value is arbitrary, but defends against parsing malicious font
+ // files causing excessive memory allocations. For reference, Adobe's
+ // SourceHanSansSC-Regular.otf has 65535 glyphs and:
+ // - its format-4 cmap table has 1581 segments.
+ // - its format-12 cmap table has 16498 segments.
+ //
+ // TODO: eliminate this constraint? If the cmap table is very large, load
+ // some or all of it lazily (at the time Font.GlyphIndex is called) instead
+ // of all of it eagerly (at the time Font.initialize is called), while
+ // keeping an upper bound on the memory used? This will make the code in
+ // cmap.go more complicated, considering that all of the Font methods are
+ // safe to call concurrently, as long as each call has a different *Buffer.
+ maxCmapSegments = 20000
+
maxGlyphDataLength = 64 * 1024
maxHintBits = 256
maxNumTables = 256
@@ -41,27 +61,34 @@ var (
errInvalidBounds = errors.New("sfnt: invalid bounds")
errInvalidCFFTable = errors.New("sfnt: invalid CFF table")
+ errInvalidCmapTable = errors.New("sfnt: invalid cmap table")
errInvalidGlyphData = errors.New("sfnt: invalid glyph data")
errInvalidHeadTable = errors.New("sfnt: invalid head table")
+ errInvalidKernTable = errors.New("sfnt: invalid kern table")
errInvalidLocaTable = errors.New("sfnt: invalid loca table")
errInvalidLocationData = errors.New("sfnt: invalid location data")
errInvalidMaxpTable = errors.New("sfnt: invalid maxp table")
errInvalidNameTable = errors.New("sfnt: invalid name table")
+ errInvalidPostTable = errors.New("sfnt: invalid post table")
errInvalidSourceData = errors.New("sfnt: invalid source data")
errInvalidTableOffset = errors.New("sfnt: invalid table offset")
errInvalidTableTagOrder = errors.New("sfnt: invalid table tag order")
errInvalidUCS2String = errors.New("sfnt: invalid UCS-2 string")
errInvalidVersion = errors.New("sfnt: invalid version")
- errUnsupportedCFFVersion = errors.New("sfnt: unsupported CFF version")
- errUnsupportedCompoundGlyph = errors.New("sfnt: unsupported compound glyph")
- errUnsupportedGlyphDataLength = errors.New("sfnt: unsupported glyph data length")
- errUnsupportedRealNumberEncoding = errors.New("sfnt: unsupported real number encoding")
- errUnsupportedNumberOfHints = errors.New("sfnt: unsupported number of hints")
- errUnsupportedNumberOfTables = errors.New("sfnt: unsupported number of tables")
- errUnsupportedPlatformEncoding = errors.New("sfnt: unsupported platform encoding")
- errUnsupportedTableOffsetLength = errors.New("sfnt: unsupported table offset or length")
- errUnsupportedType2Charstring = errors.New("sfnt: unsupported Type 2 Charstring")
+ errUnsupportedCFFVersion = errors.New("sfnt: unsupported CFF version")
+ errUnsupportedCmapEncodings = errors.New("sfnt: unsupported cmap encodings")
+ errUnsupportedCompoundGlyph = errors.New("sfnt: unsupported compound glyph")
+ errUnsupportedGlyphDataLength = errors.New("sfnt: unsupported glyph data length")
+ errUnsupportedKernTable = errors.New("sfnt: unsupported kern table")
+ errUnsupportedRealNumberEncoding = errors.New("sfnt: unsupported real number encoding")
+ errUnsupportedNumberOfCmapSegments = errors.New("sfnt: unsupported number of cmap segments")
+ errUnsupportedNumberOfHints = errors.New("sfnt: unsupported number of hints")
+ errUnsupportedNumberOfTables = errors.New("sfnt: unsupported number of tables")
+ errUnsupportedPlatformEncoding = errors.New("sfnt: unsupported platform encoding")
+ errUnsupportedPostTable = errors.New("sfnt: unsupported post table")
+ errUnsupportedTableOffsetLength = errors.New("sfnt: unsupported table offset or length")
+ errUnsupportedType2Charstring = errors.New("sfnt: unsupported Type 2 Charstring")
)
// GlyphIndex is a glyph index in a Font.
@@ -107,16 +134,16 @@ const (
// display resolution (DPI) and font size (e.g. a 12 point font).
type Units int32
-// Platform IDs and Platform Specific IDs as per
-// https://www.microsoft.com/typography/otspec/name.htm
-const (
- pidMacintosh = 1
- pidWindows = 3
-
- psidMacintoshRoman = 0
-
- psidWindowsUCS2 = 1
-)
+// scale returns x divided by unitsPerEm, rounded to the nearest fixed.Int26_6
+// value (1/64th of a pixel).
+func scale(x fixed.Int26_6, unitsPerEm Units) fixed.Int26_6 {
+ if x >= 0 {
+ x += fixed.Int26_6(unitsPerEm) / 2
+ } else {
+ x -= fixed.Int26_6(unitsPerEm) / 2
+ }
+ return x / fixed.Int26_6(unitsPerEm)
+}
func u16(b []byte) uint16 {
_ = b[1] // Bounds check hint to compiler.
@@ -208,6 +235,20 @@ func (s *source) u16(buf []byte, t table, i int) (uint16, error) {
return u16(buf), nil
}
+// u32 returns the uint32 in the table t at the relative offset i.
+//
+// buf is an optional scratch buffer as per the source.view method.
+func (s *source) u32(buf []byte, t table, i int) (uint32, error) {
+ if i < 0 || uint(t.length) < uint(i+4) {
+ return 0, errInvalidBounds
+ }
+ buf, err := s.view(buf, int(t.offset)+i, 4)
+ if err != nil {
+ return 0, err
+ }
+ return u32(buf), nil
+}
+
// table is a section of the font data.
type table struct {
offset, length uint32
@@ -247,6 +288,18 @@ func ParseReaderAt(src io.ReaderAt) (*Font, error) {
//
// The Font methods that don't take a *Buffer argument are always safe to call
// concurrently.
+//
+// Some methods provide lengths or coordinates, e.g. bounds, font metrics and
+// control points. All of these methods take a ppem parameter, which is the
+// number of pixels in 1 em, expressed as a 26.6 fixed point value. For
+// example, if 1 em is 10 pixels then ppem is fixed.I(10), which equals
+// fixed.Int26_6(10 << 6).
+//
+// To get those lengths or coordinates in terms of font units instead of
+// pixels, use ppem = fixed.Int26_6(f.UnitsPerEm()) and if those methods take a
+// font.Hinting parameter, use font.HintingNone. The return values will have
+// type fixed.Int26_6, but those numbers can be converted back to Units with no
+// further scaling necessary.
type Font struct {
src source
@@ -283,11 +336,16 @@ type Font struct {
// https://www.microsoft.com/typography/otspec/otff.htm#otttables
// "Other OpenType Tables".
//
- // TODO: hdmx, kern, vmtx? Others?
+ // TODO: hdmx, vmtx? Others?
+ kern table
cached struct {
+ glyphIndex glyphIndexFunc
indexToLocFormat bool // false means short, true means long.
isPostScript bool
+ kernNumPairs int32
+ kernOffset int32
+ postTableVersion uint32
unitsPerEm Units
// The glyph data for the glyph index i is in
@@ -306,51 +364,96 @@ func (f *Font) initialize() error {
if !f.src.valid() {
return errInvalidSourceData
}
- var buf []byte
-
- // https://www.microsoft.com/typography/otspec/otff.htm "Organization of an
- // OpenType Font" says that "The OpenType font starts with the Offset
- // Table", which is 12 bytes.
- buf, err := f.src.view(buf, 0, 12)
+ buf, isPostScript, err := f.initializeTables(nil)
if err != nil {
return err
}
+
+ // The order of these parseXxx calls matters. Later calls may depend on
+ // information parsed by earlier calls, such as the maxp table's numGlyphs.
+ // To enforce these dependencies, such information is passed and returned
+ // explicitly, and the f.cached fields are only set afterwards.
+ //
+ // When implementing new parseXxx methods, take care not to call methods
+ // such as Font.NumGlyphs that implicitly depend on f.cached fields.
+
+ buf, indexToLocFormat, unitsPerEm, err := f.parseHead(buf)
+ if err != nil {
+ return err
+ }
+ buf, numGlyphs, locations, err := f.parseMaxp(buf, indexToLocFormat, isPostScript)
+ if err != nil {
+ return err
+ }
+ buf, glyphIndex, err := f.parseCmap(buf)
+ if err != nil {
+ return err
+ }
+ buf, kernNumPairs, kernOffset, err := f.parseKern(buf)
+ if err != nil {
+ return err
+ }
+ buf, postTableVersion, err := f.parsePost(buf, numGlyphs)
+ if err != nil {
+ return err
+ }
+
+ f.cached.glyphIndex = glyphIndex
+ f.cached.indexToLocFormat = indexToLocFormat
+ f.cached.isPostScript = isPostScript
+ f.cached.kernNumPairs = kernNumPairs
+ f.cached.kernOffset = kernOffset
+ f.cached.postTableVersion = postTableVersion
+ f.cached.unitsPerEm = unitsPerEm
+ f.cached.locations = locations
+
+ return nil
+}
+
+func (f *Font) initializeTables(buf []byte) (buf1 []byte, isPostScript bool, err error) {
+ // https://www.microsoft.com/typography/otspec/otff.htm "Organization of an
+ // OpenType Font" says that "The OpenType font starts with the Offset
+ // Table", which is 12 bytes.
+ buf, err = f.src.view(buf, 0, 12)
+ if err != nil {
+ return nil, false, err
+ }
switch u32(buf) {
default:
- return errInvalidVersion
+ return nil, false, errInvalidVersion
case 0x00010000:
// No-op.
case 0x4f54544f: // "OTTO".
- f.cached.isPostScript = true
+ isPostScript = true
}
numTables := int(u16(buf[4:]))
if numTables > maxNumTables {
- return errUnsupportedNumberOfTables
+ return nil, false, errUnsupportedNumberOfTables
}
// "The Offset Table is followed immediately by the Table Record entries...
// sorted in ascending order by tag", 16 bytes each.
buf, err = f.src.view(buf, 12, 16*numTables)
if err != nil {
- return err
+ return nil, false, err
}
for b, first, prevTag := buf, true, uint32(0); len(b) > 0; b = b[16:] {
tag := u32(b)
if first {
first = false
} else if tag <= prevTag {
- return errInvalidTableTagOrder
+ return nil, false, errInvalidTableTagOrder
}
prevTag = tag
o, n := u32(b[8:12]), u32(b[12:16])
if o > maxTableOffset || n > maxTableLength {
- return errUnsupportedTableOffsetLength
+ return nil, false, errUnsupportedTableOffsetLength
}
// We ignore the checksums, but "all tables must begin on four byte
// boundries [sic]".
if o&3 != 0 {
- return errInvalidTableOffset
+ return nil, false, errInvalidTableOffset
}
// Match the 4-byte tag as a uint32. For example, "OS/2" is 0x4f532f32.
@@ -369,6 +472,8 @@ func (f *Font) initialize() error {
f.hhea = table{o, n}
case 0x686d7478:
f.hmtx = table{o, n}
+ case 0x6b65726e:
+ f.kern = table{o, n}
case 0x6c6f6361:
f.loca = table{o, n}
case 0x6d617870:
@@ -379,69 +484,258 @@ func (f *Font) initialize() error {
f.post = table{o, n}
}
}
+ return buf, isPostScript, nil
+}
- var u uint16
+func (f *Font) parseCmap(buf []byte) (buf1 []byte, glyphIndex glyphIndexFunc, err error) {
+ // https://www.microsoft.com/typography/OTSPEC/cmap.htm
- // https://www.microsoft.com/typography/otspec/head.htm
- if f.head.length != 54 {
- return errInvalidHeadTable
+ const headerSize, entrySize = 4, 8
+ if f.cmap.length < headerSize {
+ return nil, nil, errInvalidCmapTable
}
- u, err = f.src.u16(buf, f.head, 18)
+ u, err := f.src.u16(buf, f.cmap, 2)
if err != nil {
- return err
+ return nil, nil, err
+ }
+ numSubtables := int(u)
+ if f.cmap.length < headerSize+entrySize*uint32(numSubtables) {
+ return nil, nil, errInvalidCmapTable
+ }
+
+ var (
+ bestWidth int
+ bestOffset uint32
+ bestLength uint32
+ bestFormat uint16
+ )
+
+ // Scan all of the subtables, picking the widest supported one. See the
+ // platformEncodingWidth comment for more discussion of width.
+ for i := 0; i < numSubtables; i++ {
+ buf, err = f.src.view(buf, int(f.cmap.offset)+headerSize+entrySize*i, entrySize)
+ if err != nil {
+ return nil, nil, err
+ }
+ pid := u16(buf)
+ psid := u16(buf[2:])
+ width := platformEncodingWidth(pid, psid)
+ if width <= bestWidth {
+ continue
+ }
+ offset := u32(buf[4:])
+
+ if offset > f.cmap.length-4 {
+ return nil, nil, errInvalidCmapTable
+ }
+ buf, err = f.src.view(buf, int(f.cmap.offset+offset), 4)
+ if err != nil {
+ return nil, nil, err
+ }
+ format := u16(buf)
+ if !supportedCmapFormat(format, pid, psid) {
+ continue
+ }
+ length := uint32(u16(buf[2:]))
+
+ bestWidth = width
+ bestOffset = offset
+ bestLength = length
+ bestFormat = format
+ }
+
+ if bestWidth == 0 {
+ return nil, nil, errUnsupportedCmapEncodings
+ }
+ return f.makeCachedGlyphIndex(buf, bestOffset, bestLength, bestFormat)
+}
+
+func (f *Font) parseHead(buf []byte) (buf1 []byte, indexToLocFormat bool, unitsPerEm Units, err error) {
+ // https://www.microsoft.com/typography/otspec/head.htm
+
+ if f.head.length != 54 {
+ return nil, false, 0, errInvalidHeadTable
+ }
+ u, err := f.src.u16(buf, f.head, 18)
+ if err != nil {
+ return nil, false, 0, err
}
if u == 0 {
- return errInvalidHeadTable
+ return nil, false, 0, errInvalidHeadTable
}
- f.cached.unitsPerEm = Units(u)
+ unitsPerEm = Units(u)
u, err = f.src.u16(buf, f.head, 50)
if err != nil {
- return err
+ return nil, false, 0, err
}
- f.cached.indexToLocFormat = u != 0
+ indexToLocFormat = u != 0
+ return buf, indexToLocFormat, unitsPerEm, nil
+}
+func (f *Font) parseKern(buf []byte) (buf1 []byte, kernNumPairs, kernOffset int32, err error) {
+ // https://www.microsoft.com/typography/otspec/kern.htm
+
+ if f.kern.length == 0 {
+ return buf, 0, 0, nil
+ }
+ const headerSize = 4
+ if f.kern.length < headerSize {
+ return nil, 0, 0, errInvalidKernTable
+ }
+ buf, err = f.src.view(buf, int(f.kern.offset), headerSize)
+ if err != nil {
+ return nil, 0, 0, err
+ }
+ offset := int(f.kern.offset) + headerSize
+ length := int(f.kern.length) - headerSize
+
+ switch version := u16(buf); version {
+ case 0:
+ // TODO: support numTables != 1. Testing that requires finding such a font.
+ if numTables := int(u16(buf[2:])); numTables != 1 {
+ return nil, 0, 0, errUnsupportedKernTable
+ }
+ return f.parseKernVersion0(buf, offset, length)
+ case 1:
+ // TODO: find such a (proprietary?) font, and support it. Both of
+ // https://www.microsoft.com/typography/otspec/kern.htm
+ // https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6kern.html
+ // say that such fonts work on Mac OS but not on Windows.
+ }
+ return nil, 0, 0, errUnsupportedKernTable
+}
+
+func (f *Font) parseKernVersion0(buf []byte, offset, length int) (buf1 []byte, kernNumPairs, kernOffset int32, err error) {
+ const headerSize = 6
+ if length < headerSize {
+ return nil, 0, 0, errInvalidKernTable
+ }
+ buf, err = f.src.view(buf, offset, headerSize)
+ if err != nil {
+ return nil, 0, 0, err
+ }
+ if version := u16(buf); version != 0 {
+ return nil, 0, 0, errUnsupportedKernTable
+ }
+ subtableLength := int(u16(buf[2:]))
+ if subtableLength < headerSize || length < subtableLength {
+ return nil, 0, 0, errInvalidKernTable
+ }
+ if coverageBits := buf[5]; coverageBits != 0x01 {
+ // We only support horizontal kerning.
+ return nil, 0, 0, errUnsupportedKernTable
+ }
+ offset += headerSize
+ length -= headerSize
+ subtableLength -= headerSize
+
+ switch format := buf[4]; format {
+ case 0:
+ return f.parseKernFormat0(buf, offset, subtableLength)
+ case 2:
+ // TODO: find such a (proprietary?) font, and support it.
+ }
+ return nil, 0, 0, errUnsupportedKernTable
+}
+
+func (f *Font) parseKernFormat0(buf []byte, offset, length int) (buf1 []byte, kernNumPairs, kernOffset int32, err error) {
+ const headerSize, entrySize = 8, 6
+ if length < headerSize {
+ return nil, 0, 0, errInvalidKernTable
+ }
+ buf, err = f.src.view(buf, offset, headerSize)
+ if err != nil {
+ return nil, 0, 0, err
+ }
+ kernNumPairs = int32(u16(buf))
+ if length != headerSize+entrySize*int(kernNumPairs) {
+ return nil, 0, 0, errInvalidKernTable
+ }
+ return buf, kernNumPairs, int32(offset) + headerSize, nil
+}
+
+func (f *Font) parseMaxp(buf []byte, indexToLocFormat, isPostScript bool) (buf1 []byte, numGlyphs int, locations []uint32, err error) {
// https://www.microsoft.com/typography/otspec/maxp.htm
- if f.cached.isPostScript {
+
+ if isPostScript {
if f.maxp.length != 6 {
- return errInvalidMaxpTable
+ return nil, 0, nil, errInvalidMaxpTable
}
} else {
if f.maxp.length != 32 {
- return errInvalidMaxpTable
+ return nil, 0, nil, errInvalidMaxpTable
}
}
- u, err = f.src.u16(buf, f.maxp, 4)
+ u, err := f.src.u16(buf, f.maxp, 4)
if err != nil {
- return err
+ return nil, 0, nil, err
}
- numGlyphs := int(u)
+ numGlyphs = int(u)
- if f.cached.isPostScript {
+ if isPostScript {
p := cffParser{
src: &f.src,
base: int(f.cff.offset),
offset: int(f.cff.offset),
end: int(f.cff.offset + f.cff.length),
}
- f.cached.locations, err = p.parse()
+ locations, err = p.parse()
if err != nil {
- return err
+ return nil, 0, nil, err
}
} else {
- f.cached.locations, err = parseLoca(
- &f.src, f.loca, f.glyf.offset, f.cached.indexToLocFormat, numGlyphs)
+ locations, err = parseLoca(&f.src, f.loca, f.glyf.offset, indexToLocFormat, numGlyphs)
if err != nil {
- return err
+ return nil, 0, nil, err
}
}
- if len(f.cached.locations) != numGlyphs+1 {
- return errInvalidLocationData
+ if len(locations) != numGlyphs+1 {
+ return nil, 0, nil, errInvalidLocationData
}
- return nil
+
+ return buf, numGlyphs, locations, nil
}
-// TODO: func (f *Font) GlyphIndex(r rune) (x GlyphIndex, ok bool)
-// This will require parsing the cmap table.
+func (f *Font) parsePost(buf []byte, numGlyphs int) (buf1 []byte, postTableVersion uint32, err error) {
+ // https://www.microsoft.com/typography/otspec/post.htm
+
+ const headerSize = 32
+ if f.post.length < headerSize {
+ return nil, 0, errInvalidPostTable
+ }
+ u, err := f.src.u32(buf, f.post, 0)
+ if err != nil {
+ return nil, 0, err
+ }
+ switch u {
+ case 0x20000:
+ if f.post.length < headerSize+2+2*uint32(numGlyphs) {
+ return nil, 0, errInvalidPostTable
+ }
+ case 0x30000:
+ // No-op.
+ default:
+ return nil, 0, errUnsupportedPostTable
+ }
+ return buf, u, nil
+}
+
+// TODO: API for looking up glyph variants?? For example, some fonts may
+// provide both slashed and dotted zero glyphs ('0'), or regular and 'old
+// style' numerals, and users can direct software to choose a variant.
+
+type glyphIndexFunc func(f *Font, b *Buffer, r rune) (GlyphIndex, error)
+
+// GlyphIndex returns the glyph index for the given rune.
+//
+// It returns (0, nil) if there is no glyph for r.
+// https://www.microsoft.com/typography/OTSPEC/cmap.htm says that "Character
+// codes that do not correspond to any glyph in the font should be mapped to
+// glyph index 0. The glyph at this location must be a special glyph
+// representing a missing character, commonly known as .notdef."
+func (f *Font) GlyphIndex(b *Buffer, r rune) (GlyphIndex, error) {
+ return f.cached.glyphIndex(f, b, r)
+}
func (f *Font) viewGlyphData(b *Buffer, x GlyphIndex) ([]byte, error) {
xx := int(x)
@@ -458,15 +752,16 @@ func (f *Font) viewGlyphData(b *Buffer, x GlyphIndex) ([]byte, error) {
// LoadGlyphOptions are the options to the Font.LoadGlyph method.
type LoadGlyphOptions struct {
- // TODO: scale / transform / hinting.
+ // TODO: transform / hinting.
}
-// LoadGlyph returns the vector segments for the x'th glyph.
+// LoadGlyph returns the vector segments for the x'th glyph. ppem is the number
+// of pixels in 1 em.
//
// If b is non-nil, the segments become invalid to use once b is re-used.
//
// It returns ErrNotFound if the glyph index is out of range.
-func (f *Font) LoadGlyph(b *Buffer, x GlyphIndex, opts *LoadGlyphOptions) ([]Segment, error) {
+func (f *Font) LoadGlyph(b *Buffer, x GlyphIndex, ppem fixed.Int26_6, opts *LoadGlyphOptions) ([]Segment, error) {
if b == nil {
b = &Buffer{}
}
@@ -491,11 +786,153 @@ func (f *Font) LoadGlyph(b *Buffer, x GlyphIndex, opts *LoadGlyphOptions) ([]Seg
b.segments = segments
}
- // TODO: look at opts to scale / transform / hint the Buffer.segments.
+ // Scale the segments. If we want to support hinting, we'll have to push
+ // the scaling computation into the PostScript / TrueType specific glyph
+ // loading code, such as the appendGlyfSegments body, since TrueType
+ // hinting bytecode works on the scaled glyph vectors. For now, though,
+ // it's simpler to scale as a post-processing step.
+ for i := range b.segments {
+ s := &b.segments[i]
+ for j := range s.Args {
+ s.Args[j] = scale(s.Args[j]*ppem, f.cached.unitsPerEm)
+ }
+ }
+
+ // TODO: look at opts to transform / hint the Buffer.segments.
return b.segments, nil
}
+// GlyphName returns the name of the x'th glyph.
+//
+// Not every font contains glyph names. If not present, GlyphName will return
+// ("", nil).
+//
+// If present, the glyph name, provided by the font, is assumed to follow the
+// Adobe Glyph List Specification:
+// https://github.com/adobe-type-tools/agl-specification/blob/master/README.md
+//
+// This is also known as the "Adobe Glyph Naming convention", the "Adobe
+// document [for] Unicode and Glyph Names" or "PostScript glyph names".
+//
+// It returns ErrNotFound if the glyph index is out of range.
+func (f *Font) GlyphName(b *Buffer, x GlyphIndex) (string, error) {
+ if int(x) >= f.NumGlyphs() {
+ return "", ErrNotFound
+ }
+ if f.cached.postTableVersion != 0x20000 {
+ return "", nil
+ }
+ if b == nil {
+ b = &Buffer{}
+ }
+
+ // The wire format for a Version 2 post table is documented at:
+ // https://www.microsoft.com/typography/otspec/post.htm
+ const glyphNameIndexOffset = 34
+
+ buf, err := b.view(&f.src, int(f.post.offset)+glyphNameIndexOffset+2*int(x), 2)
+ if err != nil {
+ return "", err
+ }
+ u := u16(buf)
+ if u < numBuiltInPostNames {
+ i := builtInPostNamesOffsets[u+0]
+ j := builtInPostNamesOffsets[u+1]
+ return builtInPostNamesData[i:j], nil
+ }
+ // https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6post.html
+ // says that "32768 through 65535 are reserved for future use".
+ if u > 32767 {
+ return "", errUnsupportedPostTable
+ }
+ u -= numBuiltInPostNames
+
+ // Iterate through the list of Pascal-formatted strings. A linear scan is
+ // clearly O(u), which isn't great (as the obvious loop, calling
+ // Font.GlyphName, to get all of the glyph names in a font has quadratic
+ // complexity), but the wire format doesn't suggest a better alternative.
+
+ offset := glyphNameIndexOffset + 2*f.NumGlyphs()
+ buf, err = b.view(&f.src, int(f.post.offset)+offset, int(f.post.length)-offset)
+ if err != nil {
+ return "", err
+ }
+
+ for {
+ if len(buf) == 0 {
+ return "", errInvalidPostTable
+ }
+ n := 1 + int(buf[0])
+ if len(buf) < n {
+ return "", errInvalidPostTable
+ }
+ if u == 0 {
+ return string(buf[1:n]), nil
+ }
+ buf = buf[n:]
+ u--
+ }
+}
+
+// Kern returns the horizontal adjustment for the kerning pair (x0, x1). A
+// positive kern means to move the glyphs further apart. ppem is the number of
+// pixels in 1 em.
+//
+// It returns ErrNotFound if either glyph index is out of range.
+func (f *Font) Kern(b *Buffer, x0, x1 GlyphIndex, ppem fixed.Int26_6, h font.Hinting) (fixed.Int26_6, error) {
+ // TODO: how should this work with the GPOS table and CFF fonts?
+ // https://www.microsoft.com/typography/otspec/kern.htm says that
+ // "OpenType™ fonts containing CFF outlines are not supported by the 'kern'
+ // table and must use the 'GPOS' OpenType Layout table."
+
+ if n := f.NumGlyphs(); int(x0) >= n || int(x1) >= n {
+ return 0, ErrNotFound
+ }
+ // Not every font has a kern table. If it doesn't, there's no need to
+ // allocate a Buffer.
+ if f.kern.length == 0 {
+ return 0, nil
+ }
+ if b == nil {
+ b = &Buffer{}
+ }
+
+ key := uint32(x0)<<16 | uint32(x1)
+ lo, hi := int32(0), f.cached.kernNumPairs
+ for lo < hi {
+ i := (lo + hi) / 2
+
+ // TODO: this view call inside the inner loop can lead to many small
+ // reads instead of fewer larger reads, which can be expensive. We
+ // should be able to do better, although we don't want to make (one)
+ // arbitrarily large read. Perhaps we should round up reads to 4K or 8K
+ // chunks. For reference, Arial.ttf's kern table is 5472 bytes.
+ // Times_New_Roman.ttf's kern table is 5220 bytes.
+ const entrySize = 6
+ buf, err := b.view(&f.src, int(f.cached.kernOffset+i*entrySize), entrySize)
+ if err != nil {
+ return 0, err
+ }
+
+ k := u32(buf)
+ if k < key {
+ lo = i + 1
+ } else if k > key {
+ hi = i
+ } else {
+ kern := fixed.Int26_6(int16(u16(buf[4:])))
+ kern = scale(kern*ppem, f.cached.unitsPerEm)
+ if h == font.HintingFull {
+ // Quantize the fixed.Int26_6 value to the nearest pixel.
+ kern = (kern + 32) &^ 63
+ }
+ return kern, nil
+ }
+ }
+ return 0, nil
+}
+
// Name returns the name value keyed by the given NameID.
//
// It returns ErrNotFound if there is no value for that key.
@@ -512,14 +949,14 @@ func (f *Font) Name(b *Buffer, id NameID) (string, error) {
if err != nil {
return "", err
}
- nSubtables := u16(buf[2:])
- if f.name.length < headerSize+entrySize*uint32(nSubtables) {
+ numSubtables := u16(buf[2:])
+ if f.name.length < headerSize+entrySize*uint32(numSubtables) {
return "", errInvalidNameTable
}
stringOffset := u16(buf[4:])
seen := false
- for i, n := 0, int(nSubtables); i < n; i++ {
+ for i, n := 0, int(numSubtables); i < n; i++ {
buf, err := b.view(&f.src, int(f.name.offset)+headerSize+entrySize*i, entrySize)
if err != nil {
return "", err
diff --git a/vendor/golang.org/x/image/font/sfnt/sfnt_test.go b/vendor/golang.org/x/image/font/sfnt/sfnt_test.go
index 4ffd72f40d..85d96a96f1 100644
--- a/vendor/golang.org/x/image/font/sfnt/sfnt_test.go
+++ b/vendor/golang.org/x/image/font/sfnt/sfnt_test.go
@@ -6,6 +6,7 @@ package sfnt
import (
"bytes"
+ "fmt"
"io/ioutil"
"path/filepath"
"testing"
@@ -14,52 +15,48 @@ import (
"golang.org/x/image/math/fixed"
)
-func moveTo(xa, ya int) Segment {
+func moveTo(xa, ya fixed.Int26_6) Segment {
return Segment{
- Op: SegmentOpMoveTo,
- Args: [6]fixed.Int26_6{
- 0: fixed.I(xa),
- 1: fixed.I(ya),
- },
+ Op: SegmentOpMoveTo,
+ Args: [6]fixed.Int26_6{xa, ya},
}
}
-func lineTo(xa, ya int) Segment {
+func lineTo(xa, ya fixed.Int26_6) Segment {
return Segment{
- Op: SegmentOpLineTo,
- Args: [6]fixed.Int26_6{
- 0: fixed.I(xa),
- 1: fixed.I(ya),
- },
+ Op: SegmentOpLineTo,
+ Args: [6]fixed.Int26_6{xa, ya},
}
}
-func quadTo(xa, ya, xb, yb int) Segment {
+func quadTo(xa, ya, xb, yb fixed.Int26_6) Segment {
return Segment{
- Op: SegmentOpQuadTo,
- Args: [6]fixed.Int26_6{
- 0: fixed.I(xa),
- 1: fixed.I(ya),
- 2: fixed.I(xb),
- 3: fixed.I(yb),
- },
+ Op: SegmentOpQuadTo,
+ Args: [6]fixed.Int26_6{xa, ya, xb, yb},
}
}
-func cubeTo(xa, ya, xb, yb, xc, yc int) Segment {
+func cubeTo(xa, ya, xb, yb, xc, yc fixed.Int26_6) Segment {
return Segment{
- Op: SegmentOpCubeTo,
- Args: [6]fixed.Int26_6{
- 0: fixed.I(xa),
- 1: fixed.I(ya),
- 2: fixed.I(xb),
- 3: fixed.I(yb),
- 4: fixed.I(xc),
- 5: fixed.I(yc),
- },
+ Op: SegmentOpCubeTo,
+ Args: [6]fixed.Int26_6{xa, ya, xb, yb, xc, yc},
}
}
+func checkSegmentsEqual(got, want []Segment) error {
+ if len(got) != len(want) {
+ return fmt.Errorf("got %d elements, want %d\noverall:\ngot %v\nwant %v",
+ len(got), len(want), got, want)
+ }
+ for i, g := range got {
+ if w := want[i]; g != w {
+ return fmt.Errorf("element %d:\ngot %v\nwant %v\noverall:\ngot %v\nwant %v",
+ i, g, w, got, want)
+ }
+ }
+ return nil
+}
+
func TestTrueTypeParse(t *testing.T) {
f, err := Parse(goregular.TTF)
if err != nil {
@@ -88,6 +85,167 @@ func testTrueType(t *testing.T, f *Font) {
}
}
+func TestGoRegularGlyphIndex(t *testing.T) {
+ f, err := Parse(goregular.TTF)
+ if err != nil {
+ t.Fatalf("Parse: %v", err)
+ }
+
+ testCases := []struct {
+ r rune
+ want GlyphIndex
+ }{
+ // Glyphs that aren't present in Go Regular.
+ {'\u001f', 0}, // U+001F
+ {'\u0200', 0}, // U+0200 LATIN CAPITAL LETTER A WITH DOUBLE GRAVE
+ {'\u2000', 0}, // U+2000 EN QUAD
+
+ // The want values below can be verified by running the ttx tool on
+ // Go-Regular.ttf.
+ //
+ // The actual values are ad hoc, and result from whatever tools the
+ // Bigelow & Holmes type foundry used and the order in which they
+ // crafted the glyphs. They may change over time as newer versions of
+ // the font are released. In practice, though, running this test with
+ // coverage analysis suggests that it covers both the zero and non-zero
+ // cmapEntry16.offset cases for a format-4 cmap table.
+
+ {'\u0020', 3}, // U+0020 SPACE
+ {'\u0021', 4}, // U+0021 EXCLAMATION MARK
+ {'\u0022', 5}, // U+0022 QUOTATION MARK
+ {'\u0023', 6}, // U+0023 NUMBER SIGN
+ {'\u0024', 223}, // U+0024 DOLLAR SIGN
+ {'\u0025', 7}, // U+0025 PERCENT SIGN
+ {'\u0026', 8}, // U+0026 AMPERSAND
+ {'\u0027', 9}, // U+0027 APOSTROPHE
+
+ {'\u03bd', 423}, // U+03BD GREEK SMALL LETTER NU
+ {'\u03be', 424}, // U+03BE GREEK SMALL LETTER XI
+ {'\u03bf', 438}, // U+03BF GREEK SMALL LETTER OMICRON
+ {'\u03c0', 208}, // U+03C0 GREEK SMALL LETTER PI
+ {'\u03c1', 425}, // U+03C1 GREEK SMALL LETTER RHO
+ {'\u03c2', 426}, // U+03C2 GREEK SMALL LETTER FINAL SIGMA
+ }
+
+ var b Buffer
+ for _, tc := range testCases {
+ got, err := f.GlyphIndex(&b, tc.r)
+ if err != nil {
+ t.Errorf("r=%q: %v", tc.r, err)
+ continue
+ }
+ if got != tc.want {
+ t.Errorf("r=%q: got %d, want %d", tc.r, got, tc.want)
+ continue
+ }
+ }
+}
+
+func TestGlyphIndex(t *testing.T) {
+ data, err := ioutil.ReadFile(filepath.FromSlash("../testdata/cmapTest.ttf"))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ for _, format := range []int{-1, 0, 4, 12} {
+ testGlyphIndex(t, data, format)
+ }
+}
+
+func testGlyphIndex(t *testing.T, data []byte, cmapFormat int) {
+ if cmapFormat >= 0 {
+ originalSupportedCmapFormat := supportedCmapFormat
+ defer func() {
+ supportedCmapFormat = originalSupportedCmapFormat
+ }()
+ supportedCmapFormat = func(format, pid, psid uint16) bool {
+ return int(format) == cmapFormat && originalSupportedCmapFormat(format, pid, psid)
+ }
+ }
+
+ f, err := Parse(data)
+ if err != nil {
+ t.Errorf("cmapFormat=%d: %v", cmapFormat, err)
+ return
+ }
+
+ testCases := []struct {
+ r rune
+ want GlyphIndex
+ }{
+ // Glyphs that aren't present in cmapTest.ttf.
+ {'?', 0},
+ {'\ufffd', 0},
+ {'\U0001f4a9', 0},
+
+ // For a .TTF file, FontForge maps:
+ // - ".notdef" to glyph index 0.
+ // - ".null" to glyph index 1.
+ // - "nonmarkingreturn" to glyph index 2.
+
+ {'/', 0},
+ {'0', 3},
+ {'1', 4},
+ {'2', 5},
+ {'3', 0},
+
+ {'@', 0},
+ {'A', 6},
+ {'B', 7},
+ {'C', 0},
+
+ {'`', 0},
+ {'a', 8},
+ {'b', 0},
+
+ // Of the remaining runes, only U+00FF LATIN SMALL LETTER Y WITH
+ // DIAERESIS is in both the Mac Roman encoding and the cmapTest.ttf
+ // font file.
+ {'\u00fe', 0},
+ {'\u00ff', 9},
+ {'\u0100', 10},
+ {'\u0101', 11},
+ {'\u0102', 0},
+
+ {'\u4e2c', 0},
+ {'\u4e2d', 12},
+ {'\u4e2e', 0},
+
+ {'\U0001f0a0', 0},
+ {'\U0001f0a1', 13},
+ {'\U0001f0a2', 0},
+
+ {'\U0001f0b0', 0},
+ {'\U0001f0b1', 14},
+ {'\U0001f0b2', 15},
+ {'\U0001f0b3', 0},
+ }
+
+ var b Buffer
+ for _, tc := range testCases {
+ want := tc.want
+ switch {
+ case cmapFormat == 0 && tc.r > '\u007f' && tc.r != '\u00ff':
+ // cmap format 0, with the Macintosh Roman encoding, can only
+ // represent a limited set of non-ASCII runes, e.g. U+00FF.
+ want = 0
+ case cmapFormat == 4 && tc.r > '\uffff':
+ // cmap format 4 only supports the Basic Multilingual Plane (BMP).
+ want = 0
+ }
+
+ got, err := f.GlyphIndex(&b, tc.r)
+ if err != nil {
+ t.Errorf("cmapFormat=%d, r=%q: %v", cmapFormat, tc.r, err)
+ continue
+ }
+ if got != want {
+ t.Errorf("cmapFormat=%d, r=%q: got %d, want %d", cmapFormat, tc.r, got, want)
+ continue
+ }
+ }
+}
+
func TestPostScriptSegments(t *testing.T) {
// wants' vectors correspond 1-to-1 to what's in the CFFTest.sfd file,
// although OpenType/CFF and FontForge's SFD have reversed orders.
@@ -226,40 +384,32 @@ func TestTrueTypeSegments(t *testing.T) {
}
func testSegments(t *testing.T, filename string, wants [][]Segment) {
- data, err := ioutil.ReadFile(filepath.Join("..", "testdata", filename))
+ data, err := ioutil.ReadFile(filepath.FromSlash("../testdata/" + filename))
if err != nil {
- t.Fatal(err)
+ t.Fatalf("ReadFile: %v", err)
}
f, err := Parse(data)
if err != nil {
- t.Fatal(err)
+ t.Fatalf("Parse: %v", err)
}
+ ppem := fixed.Int26_6(f.UnitsPerEm())
if ng := f.NumGlyphs(); ng != len(wants) {
t.Fatalf("NumGlyphs: got %d, want %d", ng, len(wants))
}
var b Buffer
-loop:
for i, want := range wants {
- got, err := f.LoadGlyph(&b, GlyphIndex(i), nil)
+ got, err := f.LoadGlyph(&b, GlyphIndex(i), ppem, nil)
if err != nil {
t.Errorf("i=%d: LoadGlyph: %v", i, err)
continue
}
- if len(got) != len(want) {
- t.Errorf("i=%d: got %d elements, want %d\noverall:\ngot %v\nwant %v",
- i, len(got), len(want), got, want)
+ if err := checkSegmentsEqual(got, want); err != nil {
+ t.Errorf("i=%d: %v", i, err)
continue
}
- for j, g := range got {
- if w := want[j]; g != w {
- t.Errorf("i=%d: element %d:\ngot %v\nwant %v\noverall:\ngot %v\nwant %v",
- i, j, g, w, got, want)
- continue loop
- }
- }
}
- if _, err := f.LoadGlyph(nil, 0xffff, nil); err != ErrNotFound {
+ if _, err := f.LoadGlyph(nil, 0xffff, ppem, nil); err != ErrNotFound {
t.Errorf("LoadGlyph(..., 0xffff, ...):\ngot %v\nwant %v", err, ErrNotFound)
}
@@ -270,3 +420,131 @@ loop:
t.Errorf("Name:\ngot %q\nwant %q", name, want)
}
}
+
+func TestPPEM(t *testing.T) {
+ data, err := ioutil.ReadFile(filepath.FromSlash("../testdata/glyfTest.ttf"))
+ if err != nil {
+ t.Fatalf("ReadFile: %v", err)
+ }
+ f, err := Parse(data)
+ if err != nil {
+ t.Fatalf("Parse: %v", err)
+ }
+ var b Buffer
+ x, err := f.GlyphIndex(&b, '1')
+ if err != nil {
+ t.Fatalf("GlyphIndex: %v", err)
+ }
+ if x == 0 {
+ t.Fatalf("GlyphIndex: no glyph index found for the rune '1'")
+ }
+
+ testCases := []struct {
+ ppem fixed.Int26_6
+ want []Segment
+ }{{
+ ppem: fixed.Int26_6(12 << 6),
+ want: []Segment{
+ moveTo(77, 0),
+ lineTo(77, 614),
+ lineTo(230, 614),
+ lineTo(230, 0),
+ lineTo(77, 0),
+ },
+ }, {
+ ppem: fixed.Int26_6(2048),
+ want: []Segment{
+ moveTo(205, 0),
+ lineTo(205, 1638),
+ lineTo(614, 1638),
+ lineTo(614, 0),
+ lineTo(205, 0),
+ },
+ }}
+
+ for i, tc := range testCases {
+ got, err := f.LoadGlyph(&b, x, tc.ppem, nil)
+ if err != nil {
+ t.Errorf("i=%d: LoadGlyph: %v", i, err)
+ continue
+ }
+ if err := checkSegmentsEqual(got, tc.want); err != nil {
+ t.Errorf("i=%d: %v", i, err)
+ continue
+ }
+ }
+}
+
+func TestGlyphName(t *testing.T) {
+ f, err := Parse(goregular.TTF)
+ if err != nil {
+ t.Fatalf("Parse: %v", err)
+ }
+
+ testCases := []struct {
+ r rune
+ want string
+ }{
+ {'\x00', "NULL"},
+ {'!', "exclam"},
+ {'A', "A"},
+ {'{', "braceleft"},
+ {'\u00c4', "Adieresis"}, // U+00C4 LATIN CAPITAL LETTER A WITH DIAERESIS
+ {'\u2020', "dagger"}, // U+2020 DAGGER
+ {'\u2660', "spade"}, // U+2660 BLACK SPADE SUIT
+ {'\uf800', "gopher"}, // U+F800
+ {'\ufffe', ".notdef"}, // Not in the Go Regular font, so GlyphIndex returns (0, nil).
+ }
+
+ var b Buffer
+ for _, tc := range testCases {
+ x, err := f.GlyphIndex(&b, tc.r)
+ if err != nil {
+ t.Errorf("r=%q: GlyphIndex: %v", tc.r, err)
+ continue
+ }
+ got, err := f.GlyphName(&b, x)
+ if err != nil {
+ t.Errorf("r=%q: GlyphName: %v", tc.r, err)
+ continue
+ }
+ if got != tc.want {
+ t.Errorf("r=%q: got %q, want %q", tc.r, got, tc.want)
+ continue
+ }
+ }
+}
+
+func TestBuiltInPostNames(t *testing.T) {
+ testCases := []struct {
+ x GlyphIndex
+ want string
+ }{
+ {0, ".notdef"},
+ {1, ".null"},
+ {2, "nonmarkingreturn"},
+ {13, "asterisk"},
+ {36, "A"},
+ {93, "z"},
+ {123, "ocircumflex"},
+ {202, "Edieresis"},
+ {255, "Ccaron"},
+ {256, "ccaron"},
+ {257, "dcroat"},
+ {258, ""},
+ {999, ""},
+ {0xffff, ""},
+ }
+
+ for _, tc := range testCases {
+ if tc.x >= numBuiltInPostNames {
+ continue
+ }
+ i := builtInPostNamesOffsets[tc.x+0]
+ j := builtInPostNamesOffsets[tc.x+1]
+ got := builtInPostNamesData[i:j]
+ if got != tc.want {
+ t.Errorf("x=%d: got %q, want %q", tc.x, got, tc.want)
+ }
+ }
+}
diff --git a/vendor/golang.org/x/image/font/sfnt/truetype.go b/vendor/golang.org/x/image/font/sfnt/truetype.go
index 851904d103..c0eefba562 100644
--- a/vendor/golang.org/x/image/font/sfnt/truetype.go
+++ b/vendor/golang.org/x/image/font/sfnt/truetype.go
@@ -113,6 +113,11 @@ func appendGlyfSegments(dst []Segment, data []byte) ([]Segment, error) {
return nil, errInvalidGlyphData
}
+ // TODO: support compound glyphs.
+ if numContours < 0 {
+ return nil, errUnsupportedCompoundGlyph
+ }
+
// Skip the hinting instructions.
index += 2
if index > len(data) {
@@ -124,19 +129,14 @@ func appendGlyfSegments(dst []Segment, data []byte) ([]Segment, error) {
return nil, errInvalidGlyphData
}
- // TODO: support compound glyphs.
- if numContours < 0 {
- return nil, errUnsupportedCompoundGlyph
- }
-
// For simple (non-compound) glyphs, the remainder of the glyf data
// consists of (flags, x, y) points: the Bézier curve segments. These are
- // stored in columns (all the flags first, then all the x co-ordinates,
- // then all the y co-ordinates), not rows, as it compresses better.
+ // stored in columns (all the flags first, then all the x coordinates, then
+ // all the y coordinates), not rows, as it compresses better.
//
// Decoding those points in row order involves two passes. The first pass
// determines the indexes (relative to the data slice) of where the flags,
- // the x co-ordinates and the y co-ordinates each start.
+ // the x coordinates and the y coordinates each start.
flagIndex := int32(index)
xIndex, yIndex, ok := findXYIndexes(data, index, numPoints)
if !ok {
@@ -357,9 +357,18 @@ func (g *glyfIter) nextSegment() (ok bool) {
return true
}
+ // Convert the tuple (g.x, g.y) to a fixed.Point26_6, since the latter
+ // is what's held in a Segment. The input (g.x, g.y) is a pair of int16
+ // values, measured in font units, since that is what the underlying
+ // format provides. The output is a pair of fixed.Int26_6 values. A
+ // fixed.Int26_6 usually represents a 26.6 fixed number of pixels, but
+ // this here is just a straight numerical conversion, with no scaling
+ // factor. A later step scales the Segment.Args values by such a factor
+ // to convert e.g. 1792 font units to 10.5 pixels at 2048 font units
+ // per em and 12 ppem (pixels per em).
p := fixed.Point26_6{
- X: fixed.Int26_6(g.x) << 6,
- Y: fixed.Int26_6(g.y) << 6,
+ X: fixed.Int26_6(g.x),
+ Y: fixed.Int26_6(g.y),
}
if !g.firstOnCurveValid {
diff --git a/vendor/golang.org/x/image/font/testdata/cmapTest.sfd b/vendor/golang.org/x/image/font/testdata/cmapTest.sfd
new file mode 100644
index 0000000000..34c7cd6594
--- /dev/null
+++ b/vendor/golang.org/x/image/font/testdata/cmapTest.sfd
@@ -0,0 +1,265 @@
+SplineFontDB: 3.0
+FontName: cmapTest
+FullName: cmapTest
+FamilyName: cmapTest
+Weight: Regular
+Copyright: Copyright 2016 The Go Authors. All rights reserved.\nUse of this font is governed by a BSD-style license that can be found at https://golang.org/LICENSE.
+Version: 001.000
+ItalicAngle: -11.25
+UnderlinePosition: -204
+UnderlineWidth: 102
+Ascent: 1638
+Descent: 410
+LayerCount: 2
+Layer: 0 1 "Back" 1
+Layer: 1 1 "Fore" 0
+XUID: [1021 367 888937226 7862908]
+FSType: 8
+OS2Version: 0
+OS2_WeightWidthSlopeOnly: 0
+OS2_UseTypoMetrics: 1
+CreationTime: 1484386143
+ModificationTime: 1486021330
+PfmFamily: 17
+TTFWeight: 400
+TTFWidth: 5
+LineGap: 184
+VLineGap: 0
+OS2TypoAscent: 0
+OS2TypoAOffset: 1
+OS2TypoDescent: 0
+OS2TypoDOffset: 1
+OS2TypoLinegap: 184
+OS2WinAscent: 0
+OS2WinAOffset: 1
+OS2WinDescent: 0
+OS2WinDOffset: 1
+HheadAscent: 0
+HheadAOffset: 1
+HheadDescent: 0
+HheadDOffset: 1
+OS2Vendor: 'PfEd'
+MarkAttachClasses: 1
+DEI: 91125
+LangName: 1033
+Encoding: UnicodeFull
+UnicodeInterp: none
+NameList: Adobe Glyph List
+DisplaySize: -24
+AntiAlias: 1
+FitToEm: 1
+WinInfo: 126976 32 23
+BeginPrivate: 0
+EndPrivate
+TeXData: 1 0 0 346030 173015 115343 0 -1048576 115343 783286 444596 497025 792723 393216 433062 380633 303038 157286 324010 404750 52429 2506097 1059062 262144
+BeginChars: 1114112 13
+
+StartChar: zero
+Encoding: 48 48 0
+Width: 800
+VWidth: 0
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+0 0 m 29,0,-1
+ 400 800 l 25,1,-1
+ 800 0 l 25,2,-1
+ 0 0 l 29,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: one
+Encoding: 49 49 1
+Width: 800
+VWidth: 0
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+0 0 m 29,0,-1
+ 400 800 l 25,1,-1
+ 800 0 l 25,2,-1
+ 0 0 l 29,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: two
+Encoding: 50 50 2
+Width: 800
+VWidth: 0
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+0 0 m 29,0,-1
+ 400 800 l 25,1,-1
+ 800 0 l 25,2,-1
+ 0 0 l 29,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: A
+Encoding: 65 65 3
+Width: 800
+VWidth: 0
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+0 0 m 29,0,-1
+ 400 800 l 25,1,-1
+ 800 0 l 25,2,-1
+ 0 0 l 29,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: uni4E2D
+Encoding: 20013 20013 4
+Width: 800
+VWidth: 0
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+0 0 m 29,0,-1
+ 400 800 l 25,1,-1
+ 800 0 l 25,2,-1
+ 0 0 l 29,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: u1F0A1
+Encoding: 127137 127137 5
+Width: 800
+VWidth: 0
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+0 0 m 29,0,-1
+ 400 800 l 25,1,-1
+ 800 0 l 25,2,-1
+ 0 0 l 29,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: ydieresis
+Encoding: 255 255 6
+Width: 800
+VWidth: 0
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+0 0 m 29,0,-1
+ 400 800 l 25,1,-1
+ 800 0 l 25,2,-1
+ 0 0 l 29,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: Amacron
+Encoding: 256 256 7
+Width: 800
+VWidth: 0
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+0 0 m 29,0,-1
+ 400 800 l 25,1,-1
+ 800 0 l 25,2,-1
+ 0 0 l 29,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: amacron
+Encoding: 257 257 8
+Width: 800
+VWidth: 0
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+0 0 m 29,0,-1
+ 400 800 l 25,1,-1
+ 800 0 l 25,2,-1
+ 0 0 l 29,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: B
+Encoding: 66 66 9
+Width: 800
+VWidth: 0
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+0 0 m 29,0,-1
+ 400 800 l 25,1,-1
+ 800 0 l 25,2,-1
+ 0 0 l 29,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: a
+Encoding: 97 97 10
+Width: 800
+VWidth: 0
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+0 0 m 29,0,-1
+ 400 800 l 25,1,-1
+ 800 0 l 25,2,-1
+ 0 0 l 29,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: u1F0B1
+Encoding: 127153 127153 11
+Width: 800
+VWidth: 0
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+0 0 m 29,0,-1
+ 400 800 l 25,1,-1
+ 800 0 l 25,2,-1
+ 0 0 l 29,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: u1F0B2
+Encoding: 127154 127154 12
+Width: 800
+VWidth: 0
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+0 0 m 29,0,-1
+ 400 800 l 25,1,-1
+ 800 0 l 25,2,-1
+ 0 0 l 29,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+EndChars
+EndSplineFont
diff --git a/vendor/golang.org/x/image/font/testdata/cmapTest.ttf b/vendor/golang.org/x/image/font/testdata/cmapTest.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..ebe6be200c38f0944875d06dfb97da6737d2fe68
GIT binary patch
literal 2528
zcmeHJO>7%g5T3U`c9J$}0+bU9FI9>-H1^u9QW1qxC$`f{C7|X<;sV*&>s?FsuJNv;
z=2kBJTp&_~R79l+goJ7dGluHJ(~m(4bXYgX{lJ8f3o%Zbs)W0fj%^oFBItj4MTqi`tVb8>8$fzbc{%N
z(3eVeyV3vBXYWD31-f2Zi6rICAtL=t*bUbX8|^kCQ|~3{J#KBa(*H{9BiPyhs^{3{
zeH+gog6%iZxCfwjN`D!)QRt&yJv!IBM0w~O@6lRNvW)@#GUi`{eyDDrYtTGB2Ky=K
z(zokQ|1$@dh|G`S(`p1^G`arBYgqpX>;ds!K`%bx?mTy3@(w?$Kb!je;
zMm?a;z#Je%Te@Tb?=n5W((W)+?7`hRJX0v_B&C#>p-ZtwCiR#{%{S<{7-rti=|50K
zyN|Gx*}EGp*|#eaJzXi3=>@Xd?L=j#LR%^mwGYljWh6;}qfRO}&Tp?_vKxqN!VA?@
zoKR^7@bDh!{NU%-EE0~jIYiez8yakbczGQ62gh})B!DDBPc(V>x{!y`i@
zc}?z&iiU&*{Hc7w-EHcbopA$i}ju
z9`REwYm^j!#Bw19lIYDagW^Q^;PZOyl8|Yif>*
zjCqeP&@*%zH7d|7)-Ld`#dOeEZB|_`l36P=F6TW*&IB^oioBp1rev;Glgb>*rV~2N
z6{no)TL>K)RAl5;Ls<#@NP@e;iqrI+vRq!3ww#*FkA=}{&5^Zg$?@SId3GdAwl9|*
z%xU>$3EhjLMmUj9yFtzN-Bi$Y(`Qak7iQ-Q$gD(lq|ZOPT>c0E{sPQ9A*8c_Tq*y%dpzBPZmY#UN(K@K_l*+#9DW
zr9~{pZB$h$NVFUWO(||61zL2PVKwljWo1&9WdYeE8cqaGaQpX9sV(rW<68~4!B$K(iU1|n?(vEq{uO2I8^NCibXyr1BO~owBaRq*B
kwfKbcsecfd0YWAU72rG+zxMds->|a1zJ5dTtqW)W2JJ_Dr~m)}
literal 0
HcmV?d00001
diff --git a/vendor/golang.org/x/image/testdata/go-turns-two-down-ab.png b/vendor/golang.org/x/image/testdata/go-turns-two-down-ab.png
index 317c3afa150cc94b05cb6235deded60c0ed902e0..ed5a2f6b23d6ed1938b8428d5e0694fa8e1a51c8 100644
GIT binary patch
literal 21092
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