Browse Source

vendor: udpate golang.org/x/net

fatedier 6 years ago
parent
commit
cd37d22f3b
100 changed files with 11513 additions and 4141 deletions
  1. 5 3
      glide.lock
  2. 1 1
      glide.yaml
  3. 5 10
      vendor/golang.org/x/net/CONTRIBUTING.md
  4. 0 3
      vendor/golang.org/x/net/README
  5. 16 0
      vendor/golang.org/x/net/README.md
  6. 16 16
      vendor/golang.org/x/net/bpf/instructions.go
  7. 10 0
      vendor/golang.org/x/net/bpf/setter.go
  8. 2 102
      vendor/golang.org/x/net/context/context.go
  9. 20 0
      vendor/golang.org/x/net/context/go19.go
  10. 109 0
      vendor/golang.org/x/net/context/pre_go19.go
  11. 7 2
      vendor/golang.org/x/net/context/withtimeout_test.go
  12. 132 0
      vendor/golang.org/x/net/dns/dnsmessage/example_test.go
  13. 772 61
      vendor/golang.org/x/net/dns/dnsmessage/message.go
  14. 994 253
      vendor/golang.org/x/net/dns/dnsmessage/message_test.go
  15. 101 37
      vendor/golang.org/x/net/html/atom/gen.go
  16. 772 702
      vendor/golang.org/x/net/html/atom/table.go
  17. 35 10
      vendor/golang.org/x/net/html/atom/table_test.go
  18. 4 2
      vendor/golang.org/x/net/html/const.go
  19. 4 4
      vendor/golang.org/x/net/html/doc.go
  20. 3 3
      vendor/golang.org/x/net/html/foreign.go
  21. 30 3
      vendor/golang.org/x/net/html/node.go
  22. 286 75
      vendor/golang.org/x/net/html/parse.go
  23. 14 2
      vendor/golang.org/x/net/html/parse_test.go
  24. 298 0
      vendor/golang.org/x/net/html/testdata/webkit/ruby.dat
  25. 1117 0
      vendor/golang.org/x/net/html/testdata/webkit/template.dat
  26. 2 2
      vendor/golang.org/x/net/html/token.go
  27. 50 0
      vendor/golang.org/x/net/http/httpguts/guts.go
  28. 7 0
      vendor/golang.org/x/net/http/httpproxy/export_test.go
  29. 13 0
      vendor/golang.org/x/net/http/httpproxy/go19_test.go
  30. 239 0
      vendor/golang.org/x/net/http/httpproxy/proxy.go
  31. 301 0
      vendor/golang.org/x/net/http/httpproxy/proxy_test.go
  32. 1 1
      vendor/golang.org/x/net/http2/ciphers.go
  33. 1 1
      vendor/golang.org/x/net/http2/ciphers_test.go
  34. 1 1
      vendor/golang.org/x/net/http2/configure_transport.go
  35. 8 5
      vendor/golang.org/x/net/http2/errors.go
  36. 2 0
      vendor/golang.org/x/net/http2/go18.go
  37. 0 1
      vendor/golang.org/x/net/http2/go19_test.go
  38. 1 0
      vendor/golang.org/x/net/http2/h2demo/.gitignore
  39. 11 0
      vendor/golang.org/x/net/http2/h2demo/Dockerfile
  40. 134 0
      vendor/golang.org/x/net/http2/h2demo/Dockerfile.0
  41. 53 6
      vendor/golang.org/x/net/http2/h2demo/Makefile
  42. 28 0
      vendor/golang.org/x/net/http2/h2demo/deployment-prod.yaml
  43. 19 14
      vendor/golang.org/x/net/http2/h2demo/h2demo.go
  44. 17 0
      vendor/golang.org/x/net/http2/h2demo/service.yaml
  45. 15 2
      vendor/golang.org/x/net/http2/h2i/h2i.go
  46. 1 1
      vendor/golang.org/x/net/http2/hpack/encode.go
  47. 7 3
      vendor/golang.org/x/net/http2/http2.go
  48. 2 0
      vendor/golang.org/x/net/http2/not_go18.go
  49. 91 71
      vendor/golang.org/x/net/http2/server.go
  50. 86 12
      vendor/golang.org/x/net/http2/server_test.go
  51. 361 178
      vendor/golang.org/x/net/http2/transport.go
  52. 895 19
      vendor/golang.org/x/net/http2/transport_test.go
  53. 1 6
      vendor/golang.org/x/net/http2/write.go
  54. 274 0
      vendor/golang.org/x/net/icmp/diag_test.go
  55. 4 4
      vendor/golang.org/x/net/icmp/dstunreach.go
  56. 113 1
      vendor/golang.org/x/net/icmp/echo.go
  57. 31 12
      vendor/golang.org/x/net/icmp/extension.go
  58. 291 217
      vendor/golang.org/x/net/icmp/extension_test.go
  59. 0 27
      vendor/golang.org/x/net/icmp/helper.go
  60. 93 7
      vendor/golang.org/x/net/icmp/interface.go
  61. 7 2
      vendor/golang.org/x/net/icmp/ipv4.go
  62. 56 63
      vendor/golang.org/x/net/icmp/ipv4_test.go
  63. 11 6
      vendor/golang.org/x/net/icmp/message.go
  64. 133 112
      vendor/golang.org/x/net/icmp/message_test.go
  65. 25 13
      vendor/golang.org/x/net/icmp/multipart.go
  66. 470 337
      vendor/golang.org/x/net/icmp/multipart_test.go
  67. 1 1
      vendor/golang.org/x/net/icmp/packettoobig.go
  68. 4 4
      vendor/golang.org/x/net/icmp/paramprob.go
  69. 0 200
      vendor/golang.org/x/net/icmp/ping_test.go
  70. 4 4
      vendor/golang.org/x/net/icmp/timeexceeded.go
  71. 6 1
      vendor/golang.org/x/net/idna/example_test.go
  72. 95 31
      vendor/golang.org/x/net/idna/idna.go
  73. 65 0
      vendor/golang.org/x/net/idna/idna_test.go
  74. 1417 1384
      vendor/golang.org/x/net/idna/tables.go
  75. 11 6
      vendor/golang.org/x/net/idna/trieval.go
  76. 49 2
      vendor/golang.org/x/net/internal/iana/const.go
  77. 98 4
      vendor/golang.org/x/net/internal/iana/gen.go
  78. 1 1
      vendor/golang.org/x/net/internal/nettest/helper_stub.go
  79. 7 2
      vendor/golang.org/x/net/internal/nettest/stack.go
  80. 5 1
      vendor/golang.org/x/net/internal/socket/iovec_32bit.go
  81. 5 1
      vendor/golang.org/x/net/internal/socket/iovec_64bit.go
  82. 5 1
      vendor/golang.org/x/net/internal/socket/iovec_solaris_64bit.go
  83. 5 1
      vendor/golang.org/x/net/internal/socket/msghdr_bsdvar.go
  84. 5 1
      vendor/golang.org/x/net/internal/socket/msghdr_linux_32bit.go
  85. 5 1
      vendor/golang.org/x/net/internal/socket/msghdr_linux_64bit.go
  86. 5 1
      vendor/golang.org/x/net/internal/socket/msghdr_openbsd.go
  87. 4 2
      vendor/golang.org/x/net/internal/socket/msghdr_solaris_64bit.go
  88. 9 6
      vendor/golang.org/x/net/internal/socket/socket.go
  89. 66 63
      vendor/golang.org/x/net/internal/socket/socket_go1_9_test.go
  90. 3 3
      vendor/golang.org/x/net/internal/socket/sys_posix.go
  91. 61 0
      vendor/golang.org/x/net/internal/socket/zsys_darwin_arm64.go
  92. 6 0
      vendor/golang.org/x/net/internal/socket/zsys_netbsd_arm.go
  93. 168 0
      vendor/golang.org/x/net/internal/socks/client.go
  94. 158 0
      vendor/golang.org/x/net/internal/socks/dial_test.go
  95. 265 0
      vendor/golang.org/x/net/internal/socks/socks.go
  96. 241 0
      vendor/golang.org/x/net/internal/sockstest/server.go
  97. 103 0
      vendor/golang.org/x/net/internal/sockstest/server_test.go
  98. 5 5
      vendor/golang.org/x/net/ipv4/control.go
  99. 21 0
      vendor/golang.org/x/net/ipv4/control_test.go
  100. 2 2
      vendor/golang.org/x/net/ipv4/gen.go

+ 5 - 3
glide.lock

@@ -1,5 +1,5 @@
-hash: e2a62cbc49d9da8ff95682f5c0b7731a7047afdd139acddb691c51ea98f726e1
-updated: 2018-04-25T02:41:38.15698+08:00
+hash: 47d70fb6b7dee9b0e453269a7079b42488dae6c4902b4d5c93976a8b7e15f604
+updated: 2018-05-04T17:59:35.698911+08:00
 imports:
 imports:
 - name: github.com/armon/go-socks5
 - name: github.com/armon/go-socks5
   version: e75332964ef517daa070d7c38a9466a0d687e0a5
   version: e75332964ef517daa070d7c38a9466a0d687e0a5
@@ -71,11 +71,13 @@ imports:
   - twofish
   - twofish
   - xtea
   - xtea
 - name: golang.org/x/net
 - name: golang.org/x/net
-  version: e4fa1c5465ad6111f206fc92186b8c83d64adbe1
+  version: 640f4622ab692b87c2f3a94265e6f579fe38263d
   subpackages:
   subpackages:
   - bpf
   - bpf
   - context
   - context
   - internal/iana
   - internal/iana
   - internal/socket
   - internal/socket
+  - internal/socks
   - ipv4
   - ipv4
+  - proxy
 testImports: []
 testImports: []

+ 1 - 1
glide.yaml

@@ -58,7 +58,7 @@ import:
   - twofish
   - twofish
   - xtea
   - xtea
 - package: golang.org/x/net
 - package: golang.org/x/net
-  version: e4fa1c5465ad6111f206fc92186b8c83d64adbe1
+  version: 640f4622ab692b87c2f3a94265e6f579fe38263d
   subpackages:
   subpackages:
   - bpf
   - bpf
   - context
   - context

+ 5 - 10
vendor/golang.org/x/net/CONTRIBUTING.md

@@ -4,16 +4,15 @@ Go is an open source project.
 
 
 It is the work of hundreds of contributors. We appreciate your help!
 It is the work of hundreds of contributors. We appreciate your help!
 
 
-
 ## Filing issues
 ## Filing issues
 
 
 When [filing an issue](https://golang.org/issue/new), make sure to answer these five questions:
 When [filing an issue](https://golang.org/issue/new), make sure to answer these five questions:
 
 
-1. What version of Go are you using (`go version`)?
-2. What operating system and processor architecture are you using?
-3. What did you do?
-4. What did you expect to see?
-5. What did you see instead?
+1.  What version of Go are you using (`go version`)?
+2.  What operating system and processor architecture are you using?
+3.  What did you do?
+4.  What did you expect to see?
+5.  What did you see instead?
 
 
 General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker.
 General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker.
 The gophers there will answer or ask you to file an issue if you've tripped over a bug.
 The gophers there will answer or ask you to file an issue if you've tripped over a bug.
@@ -23,9 +22,5 @@ The gophers there will answer or ask you to file an issue if you've tripped over
 Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html)
 Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html)
 before sending patches.
 before sending patches.
 
 
-**We do not accept GitHub pull requests**
-(we use [Gerrit](https://code.google.com/p/gerrit/) instead for code review).
-
 Unless otherwise noted, the Go source files are distributed under
 Unless otherwise noted, the Go source files are distributed under
 the BSD-style license found in the LICENSE file.
 the BSD-style license found in the LICENSE file.
-

+ 0 - 3
vendor/golang.org/x/net/README

@@ -1,3 +0,0 @@
-This repository holds supplementary Go networking libraries.
-
-To submit changes to this repository, see http://golang.org/doc/contribute.html.

+ 16 - 0
vendor/golang.org/x/net/README.md

@@ -0,0 +1,16 @@
+# Go Networking
+
+This repository holds supplementary Go networking libraries.
+
+## Download/Install
+
+The easiest way to install is to run `go get -u golang.org/x/net`. You can
+also manually git clone the repository to `$GOPATH/src/golang.org/x/net`.
+
+## Report Issues / Send Patches
+
+This repository uses Gerrit for code changes. To learn how to submit
+changes to this repository, see https://golang.org/doc/contribute.html.
+The main issue tracker for the net repository is located at
+https://github.com/golang/go/issues. Prefix your issue with "x/net:" in the
+subject line, so it is easy to find.

+ 16 - 16
vendor/golang.org/x/net/bpf/instructions.go

@@ -198,7 +198,7 @@ func (a LoadConstant) Assemble() (RawInstruction, error) {
 	return assembleLoad(a.Dst, 4, opAddrModeImmediate, a.Val)
 	return assembleLoad(a.Dst, 4, opAddrModeImmediate, a.Val)
 }
 }
 
 
-// String returns the the instruction in assembler notation.
+// String returns the instruction in assembler notation.
 func (a LoadConstant) String() string {
 func (a LoadConstant) String() string {
 	switch a.Dst {
 	switch a.Dst {
 	case RegA:
 	case RegA:
@@ -224,7 +224,7 @@ func (a LoadScratch) Assemble() (RawInstruction, error) {
 	return assembleLoad(a.Dst, 4, opAddrModeScratch, uint32(a.N))
 	return assembleLoad(a.Dst, 4, opAddrModeScratch, uint32(a.N))
 }
 }
 
 
-// String returns the the instruction in assembler notation.
+// String returns the instruction in assembler notation.
 func (a LoadScratch) String() string {
 func (a LoadScratch) String() string {
 	switch a.Dst {
 	switch a.Dst {
 	case RegA:
 	case RegA:
@@ -248,7 +248,7 @@ func (a LoadAbsolute) Assemble() (RawInstruction, error) {
 	return assembleLoad(RegA, a.Size, opAddrModeAbsolute, a.Off)
 	return assembleLoad(RegA, a.Size, opAddrModeAbsolute, a.Off)
 }
 }
 
 
-// String returns the the instruction in assembler notation.
+// String returns the instruction in assembler notation.
 func (a LoadAbsolute) String() string {
 func (a LoadAbsolute) String() string {
 	switch a.Size {
 	switch a.Size {
 	case 1: // byte
 	case 1: // byte
@@ -277,7 +277,7 @@ func (a LoadIndirect) Assemble() (RawInstruction, error) {
 	return assembleLoad(RegA, a.Size, opAddrModeIndirect, a.Off)
 	return assembleLoad(RegA, a.Size, opAddrModeIndirect, a.Off)
 }
 }
 
 
-// String returns the the instruction in assembler notation.
+// String returns the instruction in assembler notation.
 func (a LoadIndirect) String() string {
 func (a LoadIndirect) String() string {
 	switch a.Size {
 	switch a.Size {
 	case 1: // byte
 	case 1: // byte
@@ -306,7 +306,7 @@ func (a LoadMemShift) Assemble() (RawInstruction, error) {
 	return assembleLoad(RegX, 1, opAddrModeMemShift, a.Off)
 	return assembleLoad(RegX, 1, opAddrModeMemShift, a.Off)
 }
 }
 
 
-// String returns the the instruction in assembler notation.
+// String returns the instruction in assembler notation.
 func (a LoadMemShift) String() string {
 func (a LoadMemShift) String() string {
 	return fmt.Sprintf("ldx 4*([%d]&0xf)", a.Off)
 	return fmt.Sprintf("ldx 4*([%d]&0xf)", a.Off)
 }
 }
@@ -325,7 +325,7 @@ func (a LoadExtension) Assemble() (RawInstruction, error) {
 	return assembleLoad(RegA, 4, opAddrModeAbsolute, uint32(extOffset+a.Num))
 	return assembleLoad(RegA, 4, opAddrModeAbsolute, uint32(extOffset+a.Num))
 }
 }
 
 
-// String returns the the instruction in assembler notation.
+// String returns the instruction in assembler notation.
 func (a LoadExtension) String() string {
 func (a LoadExtension) String() string {
 	switch a.Num {
 	switch a.Num {
 	case ExtLen:
 	case ExtLen:
@@ -392,7 +392,7 @@ func (a StoreScratch) Assemble() (RawInstruction, error) {
 	}, nil
 	}, nil
 }
 }
 
 
-// String returns the the instruction in assembler notation.
+// String returns the instruction in assembler notation.
 func (a StoreScratch) String() string {
 func (a StoreScratch) String() string {
 	switch a.Src {
 	switch a.Src {
 	case RegA:
 	case RegA:
@@ -418,7 +418,7 @@ func (a ALUOpConstant) Assemble() (RawInstruction, error) {
 	}, nil
 	}, nil
 }
 }
 
 
-// String returns the the instruction in assembler notation.
+// String returns the instruction in assembler notation.
 func (a ALUOpConstant) String() string {
 func (a ALUOpConstant) String() string {
 	switch a.Op {
 	switch a.Op {
 	case ALUOpAdd:
 	case ALUOpAdd:
@@ -458,7 +458,7 @@ func (a ALUOpX) Assemble() (RawInstruction, error) {
 	}, nil
 	}, nil
 }
 }
 
 
-// String returns the the instruction in assembler notation.
+// String returns the instruction in assembler notation.
 func (a ALUOpX) String() string {
 func (a ALUOpX) String() string {
 	switch a.Op {
 	switch a.Op {
 	case ALUOpAdd:
 	case ALUOpAdd:
@@ -496,7 +496,7 @@ func (a NegateA) Assemble() (RawInstruction, error) {
 	}, nil
 	}, nil
 }
 }
 
 
-// String returns the the instruction in assembler notation.
+// String returns the instruction in assembler notation.
 func (a NegateA) String() string {
 func (a NegateA) String() string {
 	return fmt.Sprintf("neg")
 	return fmt.Sprintf("neg")
 }
 }
@@ -514,7 +514,7 @@ func (a Jump) Assemble() (RawInstruction, error) {
 	}, nil
 	}, nil
 }
 }
 
 
-// String returns the the instruction in assembler notation.
+// String returns the instruction in assembler notation.
 func (a Jump) String() string {
 func (a Jump) String() string {
 	return fmt.Sprintf("ja %d", a.Skip)
 	return fmt.Sprintf("ja %d", a.Skip)
 }
 }
@@ -566,7 +566,7 @@ func (a JumpIf) Assemble() (RawInstruction, error) {
 	}, nil
 	}, nil
 }
 }
 
 
-// String returns the the instruction in assembler notation.
+// String returns the instruction in assembler notation.
 func (a JumpIf) String() string {
 func (a JumpIf) String() string {
 	switch a.Cond {
 	switch a.Cond {
 	// K == A
 	// K == A
@@ -621,7 +621,7 @@ func (a RetA) Assemble() (RawInstruction, error) {
 	}, nil
 	}, nil
 }
 }
 
 
-// String returns the the instruction in assembler notation.
+// String returns the instruction in assembler notation.
 func (a RetA) String() string {
 func (a RetA) String() string {
 	return fmt.Sprintf("ret a")
 	return fmt.Sprintf("ret a")
 }
 }
@@ -639,7 +639,7 @@ func (a RetConstant) Assemble() (RawInstruction, error) {
 	}, nil
 	}, nil
 }
 }
 
 
-// String returns the the instruction in assembler notation.
+// String returns the instruction in assembler notation.
 func (a RetConstant) String() string {
 func (a RetConstant) String() string {
 	return fmt.Sprintf("ret #%d", a.Val)
 	return fmt.Sprintf("ret #%d", a.Val)
 }
 }
@@ -654,7 +654,7 @@ func (a TXA) Assemble() (RawInstruction, error) {
 	}, nil
 	}, nil
 }
 }
 
 
-// String returns the the instruction in assembler notation.
+// String returns the instruction in assembler notation.
 func (a TXA) String() string {
 func (a TXA) String() string {
 	return fmt.Sprintf("txa")
 	return fmt.Sprintf("txa")
 }
 }
@@ -669,7 +669,7 @@ func (a TAX) Assemble() (RawInstruction, error) {
 	}, nil
 	}, nil
 }
 }
 
 
-// String returns the the instruction in assembler notation.
+// String returns the instruction in assembler notation.
 func (a TAX) String() string {
 func (a TAX) String() string {
 	return fmt.Sprintf("tax")
 	return fmt.Sprintf("tax")
 }
 }

+ 10 - 0
vendor/golang.org/x/net/bpf/setter.go

@@ -0,0 +1,10 @@
+// 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 bpf
+
+// A Setter is a type which can attach a compiled BPF filter to itself.
+type Setter interface {
+	SetBPF(filter []RawInstruction) error
+}

+ 2 - 102
vendor/golang.org/x/net/context/context.go

@@ -5,6 +5,8 @@
 // Package context defines the Context type, which carries deadlines,
 // Package context defines the Context type, which carries deadlines,
 // cancelation signals, and other request-scoped values across API boundaries
 // cancelation signals, and other request-scoped values across API boundaries
 // and between processes.
 // and between processes.
+// As of Go 1.7 this package is available in the standard library under the
+// name context.  https://golang.org/pkg/context.
 //
 //
 // Incoming requests to a server should create a Context, and outgoing calls to
 // Incoming requests to a server should create a Context, and outgoing calls to
 // servers should accept a Context. The chain of function calls between must
 // servers should accept a Context. The chain of function calls between must
@@ -36,103 +38,6 @@
 // Contexts.
 // Contexts.
 package context // import "golang.org/x/net/context"
 package context // import "golang.org/x/net/context"
 
 
-import "time"
-
-// A Context carries a deadline, a cancelation signal, and other values across
-// API boundaries.
-//
-// Context's methods may be called by multiple goroutines simultaneously.
-type Context interface {
-	// Deadline returns the time when work done on behalf of this context
-	// should be canceled. Deadline returns ok==false when no deadline is
-	// set. Successive calls to Deadline return the same results.
-	Deadline() (deadline time.Time, ok bool)
-
-	// Done returns a channel that's closed when work done on behalf of this
-	// context should be canceled. Done may return nil if this context can
-	// never be canceled. Successive calls to Done return the same value.
-	//
-	// WithCancel arranges for Done to be closed when cancel is called;
-	// WithDeadline arranges for Done to be closed when the deadline
-	// expires; WithTimeout arranges for Done to be closed when the timeout
-	// elapses.
-	//
-	// Done is provided for use in select statements:
-	//
-	//  // Stream generates values with DoSomething and sends them to out
-	//  // until DoSomething returns an error or ctx.Done is closed.
-	//  func Stream(ctx context.Context, out chan<- Value) error {
-	//  	for {
-	//  		v, err := DoSomething(ctx)
-	//  		if err != nil {
-	//  			return err
-	//  		}
-	//  		select {
-	//  		case <-ctx.Done():
-	//  			return ctx.Err()
-	//  		case out <- v:
-	//  		}
-	//  	}
-	//  }
-	//
-	// See http://blog.golang.org/pipelines for more examples of how to use
-	// a Done channel for cancelation.
-	Done() <-chan struct{}
-
-	// Err returns a non-nil error value after Done is closed. Err returns
-	// Canceled if the context was canceled or DeadlineExceeded if the
-	// context's deadline passed. No other values for Err are defined.
-	// After Done is closed, successive calls to Err return the same value.
-	Err() error
-
-	// Value returns the value associated with this context for key, or nil
-	// if no value is associated with key. Successive calls to Value with
-	// the same key returns the same result.
-	//
-	// Use context values only for request-scoped data that transits
-	// processes and API boundaries, not for passing optional parameters to
-	// functions.
-	//
-	// A key identifies a specific value in a Context. Functions that wish
-	// to store values in Context typically allocate a key in a global
-	// variable then use that key as the argument to context.WithValue and
-	// Context.Value. A key can be any type that supports equality;
-	// packages should define keys as an unexported type to avoid
-	// collisions.
-	//
-	// Packages that define a Context key should provide type-safe accessors
-	// for the values stores using that key:
-	//
-	// 	// Package user defines a User type that's stored in Contexts.
-	// 	package user
-	//
-	// 	import "golang.org/x/net/context"
-	//
-	// 	// User is the type of value stored in the Contexts.
-	// 	type User struct {...}
-	//
-	// 	// key is an unexported type for keys defined in this package.
-	// 	// This prevents collisions with keys defined in other packages.
-	// 	type key int
-	//
-	// 	// userKey is the key for user.User values in Contexts. It is
-	// 	// unexported; clients use user.NewContext and user.FromContext
-	// 	// instead of using this key directly.
-	// 	var userKey key = 0
-	//
-	// 	// NewContext returns a new Context that carries value u.
-	// 	func NewContext(ctx context.Context, u *User) context.Context {
-	// 		return context.WithValue(ctx, userKey, u)
-	// 	}
-	//
-	// 	// FromContext returns the User value stored in ctx, if any.
-	// 	func FromContext(ctx context.Context) (*User, bool) {
-	// 		u, ok := ctx.Value(userKey).(*User)
-	// 		return u, ok
-	// 	}
-	Value(key interface{}) interface{}
-}
-
 // Background returns a non-nil, empty Context. It is never canceled, has no
 // Background returns a non-nil, empty Context. It is never canceled, has no
 // values, and has no deadline. It is typically used by the main function,
 // values, and has no deadline. It is typically used by the main function,
 // initialization, and tests, and as the top-level Context for incoming
 // initialization, and tests, and as the top-level Context for incoming
@@ -149,8 +54,3 @@ func Background() Context {
 func TODO() Context {
 func TODO() Context {
 	return todo
 	return todo
 }
 }
-
-// A CancelFunc tells an operation to abandon its work.
-// A CancelFunc does not wait for the work to stop.
-// After the first call, subsequent calls to a CancelFunc do nothing.
-type CancelFunc func()

+ 20 - 0
vendor/golang.org/x/net/context/go19.go

@@ -0,0 +1,20 @@
+// 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 context
+
+import "context" // standard library's context, as of Go 1.7
+
+// A Context carries a deadline, a cancelation signal, and other values across
+// API boundaries.
+//
+// Context's methods may be called by multiple goroutines simultaneously.
+type Context = context.Context
+
+// A CancelFunc tells an operation to abandon its work.
+// A CancelFunc does not wait for the work to stop.
+// After the first call, subsequent calls to a CancelFunc do nothing.
+type CancelFunc = context.CancelFunc

+ 109 - 0
vendor/golang.org/x/net/context/pre_go19.go

@@ -0,0 +1,109 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !go1.9
+
+package context
+
+import "time"
+
+// A Context carries a deadline, a cancelation signal, and other values across
+// API boundaries.
+//
+// Context's methods may be called by multiple goroutines simultaneously.
+type Context interface {
+	// Deadline returns the time when work done on behalf of this context
+	// should be canceled. Deadline returns ok==false when no deadline is
+	// set. Successive calls to Deadline return the same results.
+	Deadline() (deadline time.Time, ok bool)
+
+	// Done returns a channel that's closed when work done on behalf of this
+	// context should be canceled. Done may return nil if this context can
+	// never be canceled. Successive calls to Done return the same value.
+	//
+	// WithCancel arranges for Done to be closed when cancel is called;
+	// WithDeadline arranges for Done to be closed when the deadline
+	// expires; WithTimeout arranges for Done to be closed when the timeout
+	// elapses.
+	//
+	// Done is provided for use in select statements:
+	//
+	//  // Stream generates values with DoSomething and sends them to out
+	//  // until DoSomething returns an error or ctx.Done is closed.
+	//  func Stream(ctx context.Context, out chan<- Value) error {
+	//  	for {
+	//  		v, err := DoSomething(ctx)
+	//  		if err != nil {
+	//  			return err
+	//  		}
+	//  		select {
+	//  		case <-ctx.Done():
+	//  			return ctx.Err()
+	//  		case out <- v:
+	//  		}
+	//  	}
+	//  }
+	//
+	// See http://blog.golang.org/pipelines for more examples of how to use
+	// a Done channel for cancelation.
+	Done() <-chan struct{}
+
+	// Err returns a non-nil error value after Done is closed. Err returns
+	// Canceled if the context was canceled or DeadlineExceeded if the
+	// context's deadline passed. No other values for Err are defined.
+	// After Done is closed, successive calls to Err return the same value.
+	Err() error
+
+	// Value returns the value associated with this context for key, or nil
+	// if no value is associated with key. Successive calls to Value with
+	// the same key returns the same result.
+	//
+	// Use context values only for request-scoped data that transits
+	// processes and API boundaries, not for passing optional parameters to
+	// functions.
+	//
+	// A key identifies a specific value in a Context. Functions that wish
+	// to store values in Context typically allocate a key in a global
+	// variable then use that key as the argument to context.WithValue and
+	// Context.Value. A key can be any type that supports equality;
+	// packages should define keys as an unexported type to avoid
+	// collisions.
+	//
+	// Packages that define a Context key should provide type-safe accessors
+	// for the values stores using that key:
+	//
+	// 	// Package user defines a User type that's stored in Contexts.
+	// 	package user
+	//
+	// 	import "golang.org/x/net/context"
+	//
+	// 	// User is the type of value stored in the Contexts.
+	// 	type User struct {...}
+	//
+	// 	// key is an unexported type for keys defined in this package.
+	// 	// This prevents collisions with keys defined in other packages.
+	// 	type key int
+	//
+	// 	// userKey is the key for user.User values in Contexts. It is
+	// 	// unexported; clients use user.NewContext and user.FromContext
+	// 	// instead of using this key directly.
+	// 	var userKey key = 0
+	//
+	// 	// NewContext returns a new Context that carries value u.
+	// 	func NewContext(ctx context.Context, u *User) context.Context {
+	// 		return context.WithValue(ctx, userKey, u)
+	// 	}
+	//
+	// 	// FromContext returns the User value stored in ctx, if any.
+	// 	func FromContext(ctx context.Context) (*User, bool) {
+	// 		u, ok := ctx.Value(userKey).(*User)
+	// 		return u, ok
+	// 	}
+	Value(key interface{}) interface{}
+}
+
+// A CancelFunc tells an operation to abandon its work.
+// A CancelFunc does not wait for the work to stop.
+// After the first call, subsequent calls to a CancelFunc do nothing.
+type CancelFunc func()

+ 7 - 2
vendor/golang.org/x/net/context/withtimeout_test.go

@@ -11,16 +11,21 @@ import (
 	"golang.org/x/net/context"
 	"golang.org/x/net/context"
 )
 )
 
 
+// This example passes a context with a timeout to tell a blocking function that
+// it should abandon its work after the timeout elapses.
 func ExampleWithTimeout() {
 func ExampleWithTimeout() {
 	// Pass a context with a timeout to tell a blocking function that it
 	// Pass a context with a timeout to tell a blocking function that it
 	// should abandon its work after the timeout elapses.
 	// should abandon its work after the timeout elapses.
-	ctx, _ := context.WithTimeout(context.Background(), 100*time.Millisecond)
+	ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond)
+	defer cancel()
+
 	select {
 	select {
-	case <-time.After(200 * time.Millisecond):
+	case <-time.After(1 * time.Second):
 		fmt.Println("overslept")
 		fmt.Println("overslept")
 	case <-ctx.Done():
 	case <-ctx.Done():
 		fmt.Println(ctx.Err()) // prints "context deadline exceeded"
 		fmt.Println(ctx.Err()) // prints "context deadline exceeded"
 	}
 	}
+
 	// Output:
 	// Output:
 	// context deadline exceeded
 	// context deadline exceeded
 }
 }

+ 132 - 0
vendor/golang.org/x/net/dns/dnsmessage/example_test.go

@@ -0,0 +1,132 @@
+// 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 dnsmessage_test
+
+import (
+	"fmt"
+	"net"
+	"strings"
+
+	"golang.org/x/net/dns/dnsmessage"
+)
+
+func mustNewName(name string) dnsmessage.Name {
+	n, err := dnsmessage.NewName(name)
+	if err != nil {
+		panic(err)
+	}
+	return n
+}
+
+func ExampleParser() {
+	msg := dnsmessage.Message{
+		Header: dnsmessage.Header{Response: true, Authoritative: true},
+		Questions: []dnsmessage.Question{
+			{
+				Name:  mustNewName("foo.bar.example.com."),
+				Type:  dnsmessage.TypeA,
+				Class: dnsmessage.ClassINET,
+			},
+			{
+				Name:  mustNewName("bar.example.com."),
+				Type:  dnsmessage.TypeA,
+				Class: dnsmessage.ClassINET,
+			},
+		},
+		Answers: []dnsmessage.Resource{
+			{
+				Header: dnsmessage.ResourceHeader{
+					Name:  mustNewName("foo.bar.example.com."),
+					Type:  dnsmessage.TypeA,
+					Class: dnsmessage.ClassINET,
+				},
+				Body: &dnsmessage.AResource{A: [4]byte{127, 0, 0, 1}},
+			},
+			{
+				Header: dnsmessage.ResourceHeader{
+					Name:  mustNewName("bar.example.com."),
+					Type:  dnsmessage.TypeA,
+					Class: dnsmessage.ClassINET,
+				},
+				Body: &dnsmessage.AResource{A: [4]byte{127, 0, 0, 2}},
+			},
+		},
+	}
+
+	buf, err := msg.Pack()
+	if err != nil {
+		panic(err)
+	}
+
+	wantName := "bar.example.com."
+
+	var p dnsmessage.Parser
+	if _, err := p.Start(buf); err != nil {
+		panic(err)
+	}
+
+	for {
+		q, err := p.Question()
+		if err == dnsmessage.ErrSectionDone {
+			break
+		}
+		if err != nil {
+			panic(err)
+		}
+
+		if q.Name.String() != wantName {
+			continue
+		}
+
+		fmt.Println("Found question for name", wantName)
+		if err := p.SkipAllQuestions(); err != nil {
+			panic(err)
+		}
+		break
+	}
+
+	var gotIPs []net.IP
+	for {
+		h, err := p.AnswerHeader()
+		if err == dnsmessage.ErrSectionDone {
+			break
+		}
+		if err != nil {
+			panic(err)
+		}
+
+		if (h.Type != dnsmessage.TypeA && h.Type != dnsmessage.TypeAAAA) || h.Class != dnsmessage.ClassINET {
+			continue
+		}
+
+		if !strings.EqualFold(h.Name.String(), wantName) {
+			if err := p.SkipAnswer(); err != nil {
+				panic(err)
+			}
+			continue
+		}
+
+		switch h.Type {
+		case dnsmessage.TypeA:
+			r, err := p.AResource()
+			if err != nil {
+				panic(err)
+			}
+			gotIPs = append(gotIPs, r.A[:])
+		case dnsmessage.TypeAAAA:
+			r, err := p.AAAAResource()
+			if err != nil {
+				panic(err)
+			}
+			gotIPs = append(gotIPs, r.AAAA[:])
+		}
+	}
+
+	fmt.Printf("Found A/AAAA records for name %s: %v\n", wantName, gotIPs)
+
+	// Output:
+	// Found question for name bar.example.com.
+	// Found A/AAAA records for name bar.example.com.: [127.0.0.2]
+}

File diff suppressed because it is too large
+ 772 - 61
vendor/golang.org/x/net/dns/dnsmessage/message.go


+ 994 - 253
vendor/golang.org/x/net/dns/dnsmessage/message_test.go

@@ -5,13 +5,29 @@
 package dnsmessage
 package dnsmessage
 
 
 import (
 import (
+	"bytes"
 	"fmt"
 	"fmt"
-	"net"
 	"reflect"
 	"reflect"
 	"strings"
 	"strings"
 	"testing"
 	"testing"
 )
 )
 
 
+func mustNewName(name string) Name {
+	n, err := NewName(name)
+	if err != nil {
+		panic(err)
+	}
+	return n
+}
+
+func mustEDNS0ResourceHeader(l int, extrc RCode, do bool) ResourceHeader {
+	h := ResourceHeader{Class: ClassINET}
+	if err := h.SetEDNS0(l, extrc, do); err != nil {
+		panic(err)
+	}
+	return h
+}
+
 func (m *Message) String() string {
 func (m *Message) String() string {
 	s := fmt.Sprintf("Message: %#v\n", &m.Header)
 	s := fmt.Sprintf("Message: %#v\n", &m.Header)
 	if len(m.Questions) > 0 {
 	if len(m.Questions) > 0 {
@@ -41,15 +57,23 @@ func (m *Message) String() string {
 	return s
 	return s
 }
 }
 
 
+func TestNameString(t *testing.T) {
+	want := "foo"
+	name := mustNewName(want)
+	if got := fmt.Sprint(name); got != want {
+		t.Errorf("got fmt.Sprint(%#v) = %s, want = %s", name, got, want)
+	}
+}
+
 func TestQuestionPackUnpack(t *testing.T) {
 func TestQuestionPackUnpack(t *testing.T) {
 	want := Question{
 	want := Question{
-		Name:  ".",
+		Name:  mustNewName("."),
 		Type:  TypeA,
 		Type:  TypeA,
 		Class: ClassINET,
 		Class: ClassINET,
 	}
 	}
-	buf, err := want.pack(make([]byte, 1, 50), map[string]int{})
+	buf, err := want.pack(make([]byte, 1, 50), map[string]int{}, 1)
 	if err != nil {
 	if err != nil {
-		t.Fatal("Packing failed:", err)
+		t.Fatal("Question.pack() =", err)
 	}
 	}
 	var p Parser
 	var p Parser
 	p.msg = buf
 	p.msg = buf
@@ -58,13 +82,39 @@ func TestQuestionPackUnpack(t *testing.T) {
 	p.off = 1
 	p.off = 1
 	got, err := p.Question()
 	got, err := p.Question()
 	if err != nil {
 	if err != nil {
-		t.Fatalf("Unpacking failed: %v\n%s", err, string(buf[1:]))
+		t.Fatalf("Parser{%q}.Question() = %v", string(buf[1:]), err)
 	}
 	}
 	if p.off != len(buf) {
 	if p.off != len(buf) {
-		t.Errorf("Unpacked different amount than packed: got n = %d, want = %d", p.off, len(buf))
+		t.Errorf("unpacked different amount than packed: got = %d, want = %d", p.off, len(buf))
 	}
 	}
 	if !reflect.DeepEqual(got, want) {
 	if !reflect.DeepEqual(got, want) {
-		t.Errorf("Got = %+v, want = %+v", got, want)
+		t.Errorf("got from Parser.Question() = %+v, want = %+v", got, want)
+	}
+}
+
+func TestName(t *testing.T) {
+	tests := []string{
+		"",
+		".",
+		"google..com",
+		"google.com",
+		"google..com.",
+		"google.com.",
+		".google.com.",
+		"www..google.com.",
+		"www.google.com.",
+	}
+
+	for _, test := range tests {
+		n, err := NewName(test)
+		if err != nil {
+			t.Errorf("NewName(%q) = %v", test, err)
+			continue
+		}
+		if ns := n.String(); ns != test {
+			t.Errorf("got %#v.String() = %q, want = %q", n, ns, test)
+			continue
+		}
 	}
 	}
 }
 }
 
 
@@ -74,10 +124,10 @@ func TestNamePackUnpack(t *testing.T) {
 		want string
 		want string
 		err  error
 		err  error
 	}{
 	}{
-		{"", ".", nil},
+		{"", "", errNonCanonicalName},
 		{".", ".", nil},
 		{".", ".", nil},
-		{"google..com", "", errZeroSegLen},
-		{"google.com", "google.com.", nil},
+		{"google..com", "", errNonCanonicalName},
+		{"google.com", "", errNonCanonicalName},
 		{"google..com.", "", errZeroSegLen},
 		{"google..com.", "", errZeroSegLen},
 		{"google.com.", "google.com.", nil},
 		{"google.com.", "google.com.", nil},
 		{".google.com.", "", errZeroSegLen},
 		{".google.com.", "", errZeroSegLen},
@@ -86,29 +136,113 @@ func TestNamePackUnpack(t *testing.T) {
 	}
 	}
 
 
 	for _, test := range tests {
 	for _, test := range tests {
-		buf, err := packName(make([]byte, 0, 30), test.in, map[string]int{})
+		in := mustNewName(test.in)
+		want := mustNewName(test.want)
+		buf, err := in.pack(make([]byte, 0, 30), map[string]int{}, 0)
 		if err != test.err {
 		if err != test.err {
-			t.Errorf("Packing of %s: got err = %v, want err = %v", test.in, err, test.err)
+			t.Errorf("got %q.pack() = %v, want = %v", test.in, err, test.err)
 			continue
 			continue
 		}
 		}
 		if test.err != nil {
 		if test.err != nil {
 			continue
 			continue
 		}
 		}
-		got, n, err := unpackName(buf, 0)
+		var got Name
+		n, err := got.unpack(buf, 0)
 		if err != nil {
 		if err != nil {
-			t.Errorf("Unpacking for %s failed: %v", test.in, err)
+			t.Errorf("%q.unpack() = %v", test.in, err)
 			continue
 			continue
 		}
 		}
 		if n != len(buf) {
 		if n != len(buf) {
 			t.Errorf(
 			t.Errorf(
-				"Unpacked different amount than packed for %s: got n = %d, want = %d",
+				"unpacked different amount than packed for %q: got = %d, want = %d",
 				test.in,
 				test.in,
 				n,
 				n,
 				len(buf),
 				len(buf),
 			)
 			)
 		}
 		}
-		if got != test.want {
-			t.Errorf("Unpacking packing of %s: got = %s, want = %s", test.in, got, test.want)
+		if got != want {
+			t.Errorf("unpacking packing of %q: got = %#v, want = %#v", test.in, got, want)
+		}
+	}
+}
+
+func TestIncompressibleName(t *testing.T) {
+	name := mustNewName("example.com.")
+	compression := map[string]int{}
+	buf, err := name.pack(make([]byte, 0, 100), compression, 0)
+	if err != nil {
+		t.Fatal("first Name.pack() =", err)
+	}
+	buf, err = name.pack(buf, compression, 0)
+	if err != nil {
+		t.Fatal("second Name.pack() =", err)
+	}
+	var n1 Name
+	off, err := n1.unpackCompressed(buf, 0, false /* allowCompression */)
+	if err != nil {
+		t.Fatal("unpacking incompressible name without pointers failed:", err)
+	}
+	var n2 Name
+	if _, err := n2.unpackCompressed(buf, off, false /* allowCompression */); err != errCompressedSRV {
+		t.Errorf("unpacking compressed incompressible name with pointers: got %v, want = %v", err, errCompressedSRV)
+	}
+}
+
+func checkErrorPrefix(err error, prefix string) bool {
+	e, ok := err.(*nestedError)
+	return ok && e.s == prefix
+}
+
+func TestHeaderUnpackError(t *testing.T) {
+	wants := []string{
+		"id",
+		"bits",
+		"questions",
+		"answers",
+		"authorities",
+		"additionals",
+	}
+	var buf []byte
+	var h header
+	for _, want := range wants {
+		n, err := h.unpack(buf, 0)
+		if n != 0 || !checkErrorPrefix(err, want) {
+			t.Errorf("got header.unpack([%d]byte, 0) = %d, %v, want = 0, %s", len(buf), n, err, want)
+		}
+		buf = append(buf, 0, 0)
+	}
+}
+
+func TestParserStart(t *testing.T) {
+	const want = "unpacking header"
+	var p Parser
+	for i := 0; i <= 1; i++ {
+		_, err := p.Start([]byte{})
+		if !checkErrorPrefix(err, want) {
+			t.Errorf("got Parser.Start(nil) = _, %v, want = _, %s", err, want)
+		}
+	}
+}
+
+func TestResourceNotStarted(t *testing.T) {
+	tests := []struct {
+		name string
+		fn   func(*Parser) error
+	}{
+		{"CNAMEResource", func(p *Parser) error { _, err := p.CNAMEResource(); return err }},
+		{"MXResource", func(p *Parser) error { _, err := p.MXResource(); return err }},
+		{"NSResource", func(p *Parser) error { _, err := p.NSResource(); return err }},
+		{"PTRResource", func(p *Parser) error { _, err := p.PTRResource(); return err }},
+		{"SOAResource", func(p *Parser) error { _, err := p.SOAResource(); return err }},
+		{"TXTResource", func(p *Parser) error { _, err := p.TXTResource(); return err }},
+		{"SRVResource", func(p *Parser) error { _, err := p.SRVResource(); return err }},
+		{"AResource", func(p *Parser) error { _, err := p.AResource(); return err }},
+		{"AAAAResource", func(p *Parser) error { _, err := p.AAAAResource(); return err }},
+	}
+
+	for _, test := range tests {
+		if err := test.fn(&Parser{}); err != ErrNotStarted {
+			t.Errorf("got Parser.%s() = _ , %v, want = _, %v", test.name, err, ErrNotStarted)
 		}
 		}
 	}
 	}
 }
 }
@@ -118,7 +252,7 @@ func TestDNSPackUnpack(t *testing.T) {
 		{
 		{
 			Questions: []Question{
 			Questions: []Question{
 				{
 				{
-					Name:  ".",
+					Name:  mustNewName("."),
 					Type:  TypeAAAA,
 					Type:  TypeAAAA,
 					Class: ClassINET,
 					Class: ClassINET,
 				},
 				},
@@ -132,15 +266,49 @@ func TestDNSPackUnpack(t *testing.T) {
 	for i, want := range wants {
 	for i, want := range wants {
 		b, err := want.Pack()
 		b, err := want.Pack()
 		if err != nil {
 		if err != nil {
-			t.Fatalf("%d: packing failed: %v", i, err)
+			t.Fatalf("%d: Message.Pack() = %v", i, err)
+		}
+		var got Message
+		err = got.Unpack(b)
+		if err != nil {
+			t.Fatalf("%d: Message.Unapck() = %v", i, err)
+		}
+		if !reflect.DeepEqual(got, want) {
+			t.Errorf("%d: Message.Pack/Unpack() roundtrip: got = %+v, want = %+v", i, &got, &want)
+		}
+	}
+}
+
+func TestDNSAppendPackUnpack(t *testing.T) {
+	wants := []Message{
+		{
+			Questions: []Question{
+				{
+					Name:  mustNewName("."),
+					Type:  TypeAAAA,
+					Class: ClassINET,
+				},
+			},
+			Answers:     []Resource{},
+			Authorities: []Resource{},
+			Additionals: []Resource{},
+		},
+		largeTestMsg(),
+	}
+	for i, want := range wants {
+		b := make([]byte, 2, 514)
+		b, err := want.AppendPack(b)
+		if err != nil {
+			t.Fatalf("%d: Message.AppendPack() = %v", i, err)
 		}
 		}
+		b = b[2:]
 		var got Message
 		var got Message
 		err = got.Unpack(b)
 		err = got.Unpack(b)
 		if err != nil {
 		if err != nil {
-			t.Fatalf("%d: unpacking failed: %v", i, err)
+			t.Fatalf("%d: Message.Unapck() = %v", i, err)
 		}
 		}
 		if !reflect.DeepEqual(got, want) {
 		if !reflect.DeepEqual(got, want) {
-			t.Errorf("%d: got = %+v, want = %+v", i, &got, &want)
+			t.Errorf("%d: Message.AppendPack/Unpack() roundtrip: got = %+v, want = %+v", i, &got, &want)
 		}
 		}
 	}
 	}
 }
 }
@@ -149,11 +317,11 @@ func TestSkipAll(t *testing.T) {
 	msg := largeTestMsg()
 	msg := largeTestMsg()
 	buf, err := msg.Pack()
 	buf, err := msg.Pack()
 	if err != nil {
 	if err != nil {
-		t.Fatal("Packing large test message:", err)
+		t.Fatal("Message.Pack() =", err)
 	}
 	}
 	var p Parser
 	var p Parser
 	if _, err := p.Start(buf); err != nil {
 	if _, err := p.Start(buf); err != nil {
-		t.Fatal(err)
+		t.Fatal("Parser.Start(non-nil) =", err)
 	}
 	}
 
 
 	tests := []struct {
 	tests := []struct {
@@ -168,12 +336,75 @@ func TestSkipAll(t *testing.T) {
 	for _, test := range tests {
 	for _, test := range tests {
 		for i := 1; i <= 3; i++ {
 		for i := 1; i <= 3; i++ {
 			if err := test.f(); err != nil {
 			if err := test.f(); err != nil {
-				t.Errorf("Call #%d to %s(): %v", i, test.name, err)
+				t.Errorf("%d: Parser.%s() = %v", i, test.name, err)
 			}
 			}
 		}
 		}
 	}
 	}
 }
 }
 
 
+func TestSkipEach(t *testing.T) {
+	msg := smallTestMsg()
+
+	buf, err := msg.Pack()
+	if err != nil {
+		t.Fatal("Message.Pack() =", err)
+	}
+	var p Parser
+	if _, err := p.Start(buf); err != nil {
+		t.Fatal("Parser.Start(non-nil) =", err)
+	}
+
+	tests := []struct {
+		name string
+		f    func() error
+	}{
+		{"SkipQuestion", p.SkipQuestion},
+		{"SkipAnswer", p.SkipAnswer},
+		{"SkipAuthority", p.SkipAuthority},
+		{"SkipAdditional", p.SkipAdditional},
+	}
+	for _, test := range tests {
+		if err := test.f(); err != nil {
+			t.Errorf("first Parser.%s() = %v, want = nil", test.name, err)
+		}
+		if err := test.f(); err != ErrSectionDone {
+			t.Errorf("second Parser.%s() = %v, want = %v", test.name, err, ErrSectionDone)
+		}
+	}
+}
+
+func TestSkipAfterRead(t *testing.T) {
+	msg := smallTestMsg()
+
+	buf, err := msg.Pack()
+	if err != nil {
+		t.Fatal("Message.Pack() =", err)
+	}
+	var p Parser
+	if _, err := p.Start(buf); err != nil {
+		t.Fatal("Parser.Srart(non-nil) =", err)
+	}
+
+	tests := []struct {
+		name string
+		skip func() error
+		read func() error
+	}{
+		{"Question", p.SkipQuestion, func() error { _, err := p.Question(); return err }},
+		{"Answer", p.SkipAnswer, func() error { _, err := p.Answer(); return err }},
+		{"Authority", p.SkipAuthority, func() error { _, err := p.Authority(); return err }},
+		{"Additional", p.SkipAdditional, func() error { _, err := p.Additional(); return err }},
+	}
+	for _, test := range tests {
+		if err := test.read(); err != nil {
+			t.Errorf("got Parser.%s() = _, %v, want = _, nil", test.name, err)
+		}
+		if err := test.skip(); err != ErrSectionDone {
+			t.Errorf("got Parser.Skip%s() = %v, want = %v", test.name, err, ErrSectionDone)
+		}
+	}
+}
+
 func TestSkipNotStarted(t *testing.T) {
 func TestSkipNotStarted(t *testing.T) {
 	var p Parser
 	var p Parser
 
 
@@ -188,7 +419,7 @@ func TestSkipNotStarted(t *testing.T) {
 	}
 	}
 	for _, test := range tests {
 	for _, test := range tests {
 		if err := test.f(); err != ErrNotStarted {
 		if err := test.f(); err != ErrNotStarted {
-			t.Errorf("Got %s() = %v, want = %v", test.name, err, ErrNotStarted)
+			t.Errorf("got Parser.%s() = %v, want = %v", test.name, err, ErrNotStarted)
 		}
 		}
 	}
 	}
 }
 }
@@ -232,344 +463,854 @@ func TestTooManyRecords(t *testing.T) {
 
 
 	for _, test := range tests {
 	for _, test := range tests {
 		if _, got := test.msg.Pack(); got != test.want {
 		if _, got := test.msg.Pack(); got != test.want {
-			t.Errorf("Packing %d %s: got = %v, want = %v", recs, test.name, got, test.want)
+			t.Errorf("got Message.Pack() for %d %s = %v, want = %v", recs, test.name, got, test.want)
 		}
 		}
 	}
 	}
 }
 }
 
 
 func TestVeryLongTxt(t *testing.T) {
 func TestVeryLongTxt(t *testing.T) {
-	want := &TXTResource{
-		ResourceHeader: ResourceHeader{
-			Name:  "foo.bar.example.com.",
+	want := Resource{
+		ResourceHeader{
+			Name:  mustNewName("foo.bar.example.com."),
 			Type:  TypeTXT,
 			Type:  TypeTXT,
 			Class: ClassINET,
 			Class: ClassINET,
 		},
 		},
-		Txt: loremIpsum,
+		&TXTResource{[]string{
+			"",
+			"",
+			"foo bar",
+			"",
+			"www.example.com",
+			"www.example.com.",
+			strings.Repeat(".", 255),
+		}},
 	}
 	}
-	buf, err := packResource(make([]byte, 0, 8000), want, map[string]int{})
+	buf, err := want.pack(make([]byte, 0, 8000), map[string]int{}, 0)
 	if err != nil {
 	if err != nil {
-		t.Fatal("Packing failed:", err)
+		t.Fatal("Resource.pack() =", err)
 	}
 	}
-	var hdr ResourceHeader
-	off, err := hdr.unpack(buf, 0)
+	var got Resource
+	off, err := got.Header.unpack(buf, 0)
 	if err != nil {
 	if err != nil {
-		t.Fatal("Unpacking ResourceHeader failed:", err)
+		t.Fatal("ResourceHeader.unpack() =", err)
 	}
 	}
-	got, n, err := unpackResource(buf, off, hdr)
+	body, n, err := unpackResourceBody(buf, off, got.Header)
 	if err != nil {
 	if err != nil {
-		t.Fatal("Unpacking failed:", err)
+		t.Fatal("unpackResourceBody() =", err)
 	}
 	}
+	got.Body = body
 	if n != len(buf) {
 	if n != len(buf) {
-		t.Errorf("Unpacked different amount than packed: got n = %d, want = %d", n, len(buf))
+		t.Errorf("unpacked different amount than packed: got = %d, want = %d", n, len(buf))
 	}
 	}
 	if !reflect.DeepEqual(got, want) {
 	if !reflect.DeepEqual(got, want) {
-		t.Errorf("Got = %+v, want = %+v", got, want)
+		t.Errorf("Resource.pack/unpack() roundtrip: got = %#v, want = %#v", got, want)
+	}
+}
+
+func TestTooLongTxt(t *testing.T) {
+	rb := TXTResource{[]string{strings.Repeat(".", 256)}}
+	if _, err := rb.pack(make([]byte, 0, 8000), map[string]int{}, 0); err != errStringTooLong {
+		t.Errorf("packing TXTResource with 256 character string: got err = %v, want = %v", err, errStringTooLong)
+	}
+}
+
+func TestStartAppends(t *testing.T) {
+	buf := make([]byte, 2, 514)
+	wantBuf := []byte{4, 44}
+	copy(buf, wantBuf)
+
+	b := NewBuilder(buf, Header{})
+	b.EnableCompression()
+
+	buf, err := b.Finish()
+	if err != nil {
+		t.Fatal("Builder.Finish() =", err)
+	}
+	if got, want := len(buf), headerLen+2; got != want {
+		t.Errorf("got len(buf) = %d, want = %d", got, want)
+	}
+	if string(buf[:2]) != string(wantBuf) {
+		t.Errorf("original data not preserved, got = %#v, want = %#v", buf[:2], wantBuf)
+	}
+}
+
+func TestStartError(t *testing.T) {
+	tests := []struct {
+		name string
+		fn   func(*Builder) error
+	}{
+		{"Questions", func(b *Builder) error { return b.StartQuestions() }},
+		{"Answers", func(b *Builder) error { return b.StartAnswers() }},
+		{"Authorities", func(b *Builder) error { return b.StartAuthorities() }},
+		{"Additionals", func(b *Builder) error { return b.StartAdditionals() }},
+	}
+
+	envs := []struct {
+		name string
+		fn   func() *Builder
+		want error
+	}{
+		{"sectionNotStarted", func() *Builder { return &Builder{section: sectionNotStarted} }, ErrNotStarted},
+		{"sectionDone", func() *Builder { return &Builder{section: sectionDone} }, ErrSectionDone},
+	}
+
+	for _, env := range envs {
+		for _, test := range tests {
+			if got := test.fn(env.fn()); got != env.want {
+				t.Errorf("got Builder{%s}.Start%s() = %v, want = %v", env.name, test.name, got, env.want)
+			}
+		}
+	}
+}
+
+func TestBuilderResourceError(t *testing.T) {
+	tests := []struct {
+		name string
+		fn   func(*Builder) error
+	}{
+		{"CNAMEResource", func(b *Builder) error { return b.CNAMEResource(ResourceHeader{}, CNAMEResource{}) }},
+		{"MXResource", func(b *Builder) error { return b.MXResource(ResourceHeader{}, MXResource{}) }},
+		{"NSResource", func(b *Builder) error { return b.NSResource(ResourceHeader{}, NSResource{}) }},
+		{"PTRResource", func(b *Builder) error { return b.PTRResource(ResourceHeader{}, PTRResource{}) }},
+		{"SOAResource", func(b *Builder) error { return b.SOAResource(ResourceHeader{}, SOAResource{}) }},
+		{"TXTResource", func(b *Builder) error { return b.TXTResource(ResourceHeader{}, TXTResource{}) }},
+		{"SRVResource", func(b *Builder) error { return b.SRVResource(ResourceHeader{}, SRVResource{}) }},
+		{"AResource", func(b *Builder) error { return b.AResource(ResourceHeader{}, AResource{}) }},
+		{"AAAAResource", func(b *Builder) error { return b.AAAAResource(ResourceHeader{}, AAAAResource{}) }},
+		{"OPTResource", func(b *Builder) error { return b.OPTResource(ResourceHeader{}, OPTResource{}) }},
+	}
+
+	envs := []struct {
+		name string
+		fn   func() *Builder
+		want error
+	}{
+		{"sectionNotStarted", func() *Builder { return &Builder{section: sectionNotStarted} }, ErrNotStarted},
+		{"sectionHeader", func() *Builder { return &Builder{section: sectionHeader} }, ErrNotStarted},
+		{"sectionQuestions", func() *Builder { return &Builder{section: sectionQuestions} }, ErrNotStarted},
+		{"sectionDone", func() *Builder { return &Builder{section: sectionDone} }, ErrSectionDone},
+	}
+
+	for _, env := range envs {
+		for _, test := range tests {
+			if got := test.fn(env.fn()); got != env.want {
+				t.Errorf("got Builder{%s}.%s() = %v, want = %v", env.name, test.name, got, env.want)
+			}
+		}
+	}
+}
+
+func TestFinishError(t *testing.T) {
+	var b Builder
+	want := ErrNotStarted
+	if _, got := b.Finish(); got != want {
+		t.Errorf("got Builder.Finish() = %v, want = %v", got, want)
+	}
+}
+
+func TestBuilder(t *testing.T) {
+	msg := largeTestMsg()
+	want, err := msg.Pack()
+	if err != nil {
+		t.Fatal("Message.Pack() =", err)
+	}
+
+	b := NewBuilder(nil, msg.Header)
+	b.EnableCompression()
+
+	if err := b.StartQuestions(); err != nil {
+		t.Fatal("Builder.StartQuestions() =", err)
+	}
+	for _, q := range msg.Questions {
+		if err := b.Question(q); err != nil {
+			t.Fatalf("Builder.Question(%#v) = %v", q, err)
+		}
+	}
+
+	if err := b.StartAnswers(); err != nil {
+		t.Fatal("Builder.StartAnswers() =", err)
+	}
+	for _, a := range msg.Answers {
+		switch a.Header.Type {
+		case TypeA:
+			if err := b.AResource(a.Header, *a.Body.(*AResource)); err != nil {
+				t.Fatalf("Builder.AResource(%#v) = %v", a, err)
+			}
+		case TypeNS:
+			if err := b.NSResource(a.Header, *a.Body.(*NSResource)); err != nil {
+				t.Fatalf("Builder.NSResource(%#v) = %v", a, err)
+			}
+		case TypeCNAME:
+			if err := b.CNAMEResource(a.Header, *a.Body.(*CNAMEResource)); err != nil {
+				t.Fatalf("Builder.CNAMEResource(%#v) = %v", a, err)
+			}
+		case TypeSOA:
+			if err := b.SOAResource(a.Header, *a.Body.(*SOAResource)); err != nil {
+				t.Fatalf("Builder.SOAResource(%#v) = %v", a, err)
+			}
+		case TypePTR:
+			if err := b.PTRResource(a.Header, *a.Body.(*PTRResource)); err != nil {
+				t.Fatalf("Builder.PTRResource(%#v) = %v", a, err)
+			}
+		case TypeMX:
+			if err := b.MXResource(a.Header, *a.Body.(*MXResource)); err != nil {
+				t.Fatalf("Builder.MXResource(%#v) = %v", a, err)
+			}
+		case TypeTXT:
+			if err := b.TXTResource(a.Header, *a.Body.(*TXTResource)); err != nil {
+				t.Fatalf("Builder.TXTResource(%#v) = %v", a, err)
+			}
+		case TypeAAAA:
+			if err := b.AAAAResource(a.Header, *a.Body.(*AAAAResource)); err != nil {
+				t.Fatalf("Builder.AAAAResource(%#v) = %v", a, err)
+			}
+		case TypeSRV:
+			if err := b.SRVResource(a.Header, *a.Body.(*SRVResource)); err != nil {
+				t.Fatalf("Builder.SRVResource(%#v) = %v", a, err)
+			}
+		}
+	}
+
+	if err := b.StartAuthorities(); err != nil {
+		t.Fatal("Builder.StartAuthorities() =", err)
+	}
+	for _, a := range msg.Authorities {
+		if err := b.NSResource(a.Header, *a.Body.(*NSResource)); err != nil {
+			t.Fatalf("Builder.NSResource(%#v) = %v", a, err)
+		}
+	}
+
+	if err := b.StartAdditionals(); err != nil {
+		t.Fatal("Builder.StartAdditionals() =", err)
+	}
+	for _, a := range msg.Additionals {
+		switch a.Body.(type) {
+		case *TXTResource:
+			if err := b.TXTResource(a.Header, *a.Body.(*TXTResource)); err != nil {
+				t.Fatalf("Builder.TXTResource(%#v) = %v", a, err)
+			}
+		case *OPTResource:
+			if err := b.OPTResource(a.Header, *a.Body.(*OPTResource)); err != nil {
+				t.Fatalf("Builder.OPTResource(%#v) = %v", a, err)
+			}
+		}
+	}
+
+	got, err := b.Finish()
+	if err != nil {
+		t.Fatal("Builder.Finish() =", err)
+	}
+	if !bytes.Equal(got, want) {
+		t.Fatalf("got from Builder.Finish() = %#v\nwant = %#v", got, want)
 	}
 	}
 }
 }
 
 
-func ExampleHeaderSearch() {
+func TestResourcePack(t *testing.T) {
+	for _, tt := range []struct {
+		m   Message
+		err error
+	}{
+		{
+			Message{
+				Questions: []Question{
+					{
+						Name:  mustNewName("."),
+						Type:  TypeAAAA,
+						Class: ClassINET,
+					},
+				},
+				Answers: []Resource{{ResourceHeader{}, nil}},
+			},
+			&nestedError{"packing Answer", errNilResouceBody},
+		},
+		{
+			Message{
+				Questions: []Question{
+					{
+						Name:  mustNewName("."),
+						Type:  TypeAAAA,
+						Class: ClassINET,
+					},
+				},
+				Authorities: []Resource{{ResourceHeader{}, (*NSResource)(nil)}},
+			},
+			&nestedError{"packing Authority",
+				&nestedError{"ResourceHeader",
+					&nestedError{"Name", errNonCanonicalName},
+				},
+			},
+		},
+		{
+			Message{
+				Questions: []Question{
+					{
+						Name:  mustNewName("."),
+						Type:  TypeA,
+						Class: ClassINET,
+					},
+				},
+				Additionals: []Resource{{ResourceHeader{}, nil}},
+			},
+			&nestedError{"packing Additional", errNilResouceBody},
+		},
+	} {
+		_, err := tt.m.Pack()
+		if !reflect.DeepEqual(err, tt.err) {
+			t.Errorf("got Message{%v}.Pack() = %v, want %v", tt.m, err, tt.err)
+		}
+	}
+}
+
+func TestOptionPackUnpack(t *testing.T) {
+	for _, tt := range []struct {
+		name     string
+		w        []byte // wire format of m.Additionals
+		m        Message
+		dnssecOK bool
+		extRCode RCode
+	}{
+		{
+			name: "without EDNS(0) options",
+			w: []byte{
+				0x00, 0x00, 0x29, 0x10, 0x00, 0xfe, 0x00, 0x80,
+				0x00, 0x00, 0x00,
+			},
+			m: Message{
+				Header: Header{RCode: RCodeFormatError},
+				Questions: []Question{
+					{
+						Name:  mustNewName("."),
+						Type:  TypeA,
+						Class: ClassINET,
+					},
+				},
+				Additionals: []Resource{
+					{
+						mustEDNS0ResourceHeader(4096, 0xfe0|RCodeFormatError, true),
+						&OPTResource{},
+					},
+				},
+			},
+			dnssecOK: true,
+			extRCode: 0xfe0 | RCodeFormatError,
+		},
+		{
+			name: "with EDNS(0) options",
+			w: []byte{
+				0x00, 0x00, 0x29, 0x10, 0x00, 0xff, 0x00, 0x00,
+				0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x02, 0x00,
+				0x00, 0x00, 0x0b, 0x00, 0x02, 0x12, 0x34,
+			},
+			m: Message{
+				Header: Header{RCode: RCodeServerFailure},
+				Questions: []Question{
+					{
+						Name:  mustNewName("."),
+						Type:  TypeAAAA,
+						Class: ClassINET,
+					},
+				},
+				Additionals: []Resource{
+					{
+						mustEDNS0ResourceHeader(4096, 0xff0|RCodeServerFailure, false),
+						&OPTResource{
+							Options: []Option{
+								{
+									Code: 12, // see RFC 7828
+									Data: []byte{0x00, 0x00},
+								},
+								{
+									Code: 11, // see RFC 7830
+									Data: []byte{0x12, 0x34},
+								},
+							},
+						},
+					},
+				},
+			},
+			dnssecOK: false,
+			extRCode: 0xff0 | RCodeServerFailure,
+		},
+		{
+			// Containing multiple OPT resources in a
+			// message is invalid, but it's necessary for
+			// protocol conformance testing.
+			name: "with multiple OPT resources",
+			w: []byte{
+				0x00, 0x00, 0x29, 0x10, 0x00, 0xff, 0x00, 0x00,
+				0x00, 0x00, 0x06, 0x00, 0x0b, 0x00, 0x02, 0x12,
+				0x34, 0x00, 0x00, 0x29, 0x10, 0x00, 0xff, 0x00,
+				0x00, 0x00, 0x00, 0x06, 0x00, 0x0c, 0x00, 0x02,
+				0x00, 0x00,
+			},
+			m: Message{
+				Header: Header{RCode: RCodeNameError},
+				Questions: []Question{
+					{
+						Name:  mustNewName("."),
+						Type:  TypeAAAA,
+						Class: ClassINET,
+					},
+				},
+				Additionals: []Resource{
+					{
+						mustEDNS0ResourceHeader(4096, 0xff0|RCodeNameError, false),
+						&OPTResource{
+							Options: []Option{
+								{
+									Code: 11, // see RFC 7830
+									Data: []byte{0x12, 0x34},
+								},
+							},
+						},
+					},
+					{
+						mustEDNS0ResourceHeader(4096, 0xff0|RCodeNameError, false),
+						&OPTResource{
+							Options: []Option{
+								{
+									Code: 12, // see RFC 7828
+									Data: []byte{0x00, 0x00},
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+	} {
+		w, err := tt.m.Pack()
+		if err != nil {
+			t.Errorf("Message.Pack() for %s = %v", tt.name, err)
+			continue
+		}
+		if !bytes.Equal(w[len(w)-len(tt.w):], tt.w) {
+			t.Errorf("got Message.Pack() for %s = %#v, want %#v", tt.name, w[len(w)-len(tt.w):], tt.w)
+			continue
+		}
+		var m Message
+		if err := m.Unpack(w); err != nil {
+			t.Errorf("Message.Unpack() for %s = %v", tt.name, err)
+			continue
+		}
+		if !reflect.DeepEqual(m.Additionals, tt.m.Additionals) {
+			t.Errorf("got Message.Pack/Unpack() roundtrip for %s = %+v, want %+v", tt.name, m, tt.m)
+			continue
+		}
+	}
+}
+
+func benchmarkParsingSetup() ([]byte, error) {
+	name := mustNewName("foo.bar.example.com.")
 	msg := Message{
 	msg := Message{
 		Header: Header{Response: true, Authoritative: true},
 		Header: Header{Response: true, Authoritative: true},
 		Questions: []Question{
 		Questions: []Question{
 			{
 			{
-				Name:  "foo.bar.example.com.",
-				Type:  TypeA,
-				Class: ClassINET,
-			},
-			{
-				Name:  "bar.example.com.",
+				Name:  name,
 				Type:  TypeA,
 				Type:  TypeA,
 				Class: ClassINET,
 				Class: ClassINET,
 			},
 			},
 		},
 		},
 		Answers: []Resource{
 		Answers: []Resource{
-			&AResource{
-				ResourceHeader: ResourceHeader{
-					Name:  "foo.bar.example.com.",
-					Type:  TypeA,
+			{
+				ResourceHeader{
+					Name:  name,
 					Class: ClassINET,
 					Class: ClassINET,
 				},
 				},
-				A: [4]byte{127, 0, 0, 1},
+				&AResource{[4]byte{}},
 			},
 			},
-			&AResource{
-				ResourceHeader: ResourceHeader{
-					Name:  "bar.example.com.",
-					Type:  TypeA,
+			{
+				ResourceHeader{
+					Name:  name,
 					Class: ClassINET,
 					Class: ClassINET,
 				},
 				},
-				A: [4]byte{127, 0, 0, 2},
+				&AAAAResource{[16]byte{}},
+			},
+			{
+				ResourceHeader{
+					Name:  name,
+					Class: ClassINET,
+				},
+				&CNAMEResource{name},
+			},
+			{
+				ResourceHeader{
+					Name:  name,
+					Class: ClassINET,
+				},
+				&NSResource{name},
 			},
 			},
 		},
 		},
 	}
 	}
 
 
 	buf, err := msg.Pack()
 	buf, err := msg.Pack()
 	if err != nil {
 	if err != nil {
-		panic(err)
+		return nil, fmt.Errorf("Message.Pack() = %v", err)
 	}
 	}
+	return buf, nil
+}
 
 
-	wantName := "bar.example.com."
-
+func benchmarkParsing(tb testing.TB, buf []byte) {
 	var p Parser
 	var p Parser
 	if _, err := p.Start(buf); err != nil {
 	if _, err := p.Start(buf); err != nil {
-		panic(err)
+		tb.Fatal("Parser.Start(non-nil) =", err)
 	}
 	}
 
 
 	for {
 	for {
-		q, err := p.Question()
+		_, err := p.Question()
 		if err == ErrSectionDone {
 		if err == ErrSectionDone {
 			break
 			break
 		}
 		}
 		if err != nil {
 		if err != nil {
-			panic(err)
-		}
-
-		if q.Name != wantName {
-			continue
-		}
-
-		fmt.Println("Found question for name", wantName)
-		if err := p.SkipAllQuestions(); err != nil {
-			panic(err)
+			tb.Fatal("Parser.Question() =", err)
 		}
 		}
-		break
 	}
 	}
 
 
-	var gotIPs []net.IP
 	for {
 	for {
 		h, err := p.AnswerHeader()
 		h, err := p.AnswerHeader()
 		if err == ErrSectionDone {
 		if err == ErrSectionDone {
 			break
 			break
 		}
 		}
 		if err != nil {
 		if err != nil {
-			panic(err)
-		}
-
-		if (h.Type != TypeA && h.Type != TypeAAAA) || h.Class != ClassINET {
-			continue
+			tb.Fatal("Parser.AnswerHeader() =", err)
 		}
 		}
 
 
-		if !strings.EqualFold(h.Name, wantName) {
-			if err := p.SkipAnswer(); err != nil {
-				panic(err)
+		switch h.Type {
+		case TypeA:
+			if _, err := p.AResource(); err != nil {
+				tb.Fatal("Parser.AResource() =", err)
 			}
 			}
-			continue
-		}
-		a, err := p.Answer()
-		if err != nil {
-			panic(err)
+		case TypeAAAA:
+			if _, err := p.AAAAResource(); err != nil {
+				tb.Fatal("Parser.AAAAResource() =", err)
+			}
+		case TypeCNAME:
+			if _, err := p.CNAMEResource(); err != nil {
+				tb.Fatal("Parser.CNAMEResource() =", err)
+			}
+		case TypeNS:
+			if _, err := p.NSResource(); err != nil {
+				tb.Fatal("Parser.NSResource() =", err)
+			}
+		case TypeOPT:
+			if _, err := p.OPTResource(); err != nil {
+				tb.Fatal("Parser.OPTResource() =", err)
+			}
+		default:
+			tb.Fatalf("got unknown type: %T", h)
 		}
 		}
+	}
+}
 
 
-		switch r := a.(type) {
-		default:
-			panic(fmt.Sprintf("unknown type: %T", r))
-		case *AResource:
-			gotIPs = append(gotIPs, r.A[:])
-		case *AAAAResource:
-			gotIPs = append(gotIPs, r.AAAA[:])
+func BenchmarkParsing(b *testing.B) {
+	buf, err := benchmarkParsingSetup()
+	if err != nil {
+		b.Fatal(err)
+	}
+
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		benchmarkParsing(b, buf)
+	}
+}
+
+func TestParsingAllocs(t *testing.T) {
+	buf, err := benchmarkParsingSetup()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if allocs := testing.AllocsPerRun(100, func() { benchmarkParsing(t, buf) }); allocs > 0.5 {
+		t.Errorf("allocations during parsing: got = %f, want ~0", allocs)
+	}
+}
+
+func benchmarkBuildingSetup() (Name, []byte) {
+	name := mustNewName("foo.bar.example.com.")
+	buf := make([]byte, 0, packStartingCap)
+	return name, buf
+}
+
+func benchmarkBuilding(tb testing.TB, name Name, buf []byte) {
+	bld := NewBuilder(buf, Header{Response: true, Authoritative: true})
+
+	if err := bld.StartQuestions(); err != nil {
+		tb.Fatal("Builder.StartQuestions() =", err)
+	}
+	q := Question{
+		Name:  name,
+		Type:  TypeA,
+		Class: ClassINET,
+	}
+	if err := bld.Question(q); err != nil {
+		tb.Fatalf("Builder.Question(%+v) = %v", q, err)
+	}
+
+	hdr := ResourceHeader{
+		Name:  name,
+		Class: ClassINET,
+	}
+	if err := bld.StartAnswers(); err != nil {
+		tb.Fatal("Builder.StartQuestions() =", err)
+	}
+
+	ar := AResource{[4]byte{}}
+	if err := bld.AResource(hdr, ar); err != nil {
+		tb.Fatalf("Builder.AResource(%+v, %+v) = %v", hdr, ar, err)
+	}
+
+	aaar := AAAAResource{[16]byte{}}
+	if err := bld.AAAAResource(hdr, aaar); err != nil {
+		tb.Fatalf("Builder.AAAAResource(%+v, %+v) = %v", hdr, aaar, err)
+	}
+
+	cnr := CNAMEResource{name}
+	if err := bld.CNAMEResource(hdr, cnr); err != nil {
+		tb.Fatalf("Builder.CNAMEResource(%+v, %+v) = %v", hdr, cnr, err)
+	}
+
+	nsr := NSResource{name}
+	if err := bld.NSResource(hdr, nsr); err != nil {
+		tb.Fatalf("Builder.NSResource(%+v, %+v) = %v", hdr, nsr, err)
+	}
+
+	extrc := 0xfe0 | RCodeNotImplemented
+	if err := (&hdr).SetEDNS0(4096, extrc, true); err != nil {
+		tb.Fatalf("ResourceHeader.SetEDNS0(4096, %#x, true) = %v", extrc, err)
+	}
+	optr := OPTResource{}
+	if err := bld.OPTResource(hdr, optr); err != nil {
+		tb.Fatalf("Builder.OPTResource(%+v, %+v) = %v", hdr, optr, err)
+	}
+
+	if _, err := bld.Finish(); err != nil {
+		tb.Fatal("Builder.Finish() =", err)
+	}
+}
+
+func BenchmarkBuilding(b *testing.B) {
+	name, buf := benchmarkBuildingSetup()
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		benchmarkBuilding(b, name, buf)
+	}
+}
+
+func TestBuildingAllocs(t *testing.T) {
+	name, buf := benchmarkBuildingSetup()
+	if allocs := testing.AllocsPerRun(100, func() { benchmarkBuilding(t, name, buf) }); allocs > 0.5 {
+		t.Errorf("allocations during building: got = %f, want ~0", allocs)
+	}
+}
+
+func smallTestMsg() Message {
+	name := mustNewName("example.com.")
+	return Message{
+		Header: Header{Response: true, Authoritative: true},
+		Questions: []Question{
+			{
+				Name:  name,
+				Type:  TypeA,
+				Class: ClassINET,
+			},
+		},
+		Answers: []Resource{
+			{
+				ResourceHeader{
+					Name:  name,
+					Type:  TypeA,
+					Class: ClassINET,
+				},
+				&AResource{[4]byte{127, 0, 0, 1}},
+			},
+		},
+		Authorities: []Resource{
+			{
+				ResourceHeader{
+					Name:  name,
+					Type:  TypeA,
+					Class: ClassINET,
+				},
+				&AResource{[4]byte{127, 0, 0, 1}},
+			},
+		},
+		Additionals: []Resource{
+			{
+				ResourceHeader{
+					Name:  name,
+					Type:  TypeA,
+					Class: ClassINET,
+				},
+				&AResource{[4]byte{127, 0, 0, 1}},
+			},
+		},
+	}
+}
+
+func BenchmarkPack(b *testing.B) {
+	msg := largeTestMsg()
+
+	b.ReportAllocs()
+
+	for i := 0; i < b.N; i++ {
+		if _, err := msg.Pack(); err != nil {
+			b.Fatal("Message.Pack() =", err)
 		}
 		}
 	}
 	}
+}
+
+func BenchmarkAppendPack(b *testing.B) {
+	msg := largeTestMsg()
+	buf := make([]byte, 0, packStartingCap)
 
 
-	fmt.Printf("Found A/AAAA records for name %s: %v\n", wantName, gotIPs)
+	b.ReportAllocs()
 
 
-	// Output:
-	// Found question for name bar.example.com.
-	// Found A/AAAA records for name bar.example.com.: [127.0.0.2]
+	for i := 0; i < b.N; i++ {
+		if _, err := msg.AppendPack(buf[:0]); err != nil {
+			b.Fatal("Message.AppendPack() = ", err)
+		}
+	}
 }
 }
 
 
 func largeTestMsg() Message {
 func largeTestMsg() Message {
+	name := mustNewName("foo.bar.example.com.")
 	return Message{
 	return Message{
 		Header: Header{Response: true, Authoritative: true},
 		Header: Header{Response: true, Authoritative: true},
 		Questions: []Question{
 		Questions: []Question{
 			{
 			{
-				Name:  "foo.bar.example.com.",
+				Name:  name,
 				Type:  TypeA,
 				Type:  TypeA,
 				Class: ClassINET,
 				Class: ClassINET,
 			},
 			},
 		},
 		},
 		Answers: []Resource{
 		Answers: []Resource{
-			&AResource{
-				ResourceHeader: ResourceHeader{
-					Name:  "foo.bar.example.com.",
+			{
+				ResourceHeader{
+					Name:  name,
 					Type:  TypeA,
 					Type:  TypeA,
 					Class: ClassINET,
 					Class: ClassINET,
 				},
 				},
-				A: [4]byte{127, 0, 0, 1},
+				&AResource{[4]byte{127, 0, 0, 1}},
 			},
 			},
-			&AResource{
-				ResourceHeader: ResourceHeader{
-					Name:  "foo.bar.example.com.",
+			{
+				ResourceHeader{
+					Name:  name,
 					Type:  TypeA,
 					Type:  TypeA,
 					Class: ClassINET,
 					Class: ClassINET,
 				},
 				},
-				A: [4]byte{127, 0, 0, 2},
+				&AResource{[4]byte{127, 0, 0, 2}},
+			},
+			{
+				ResourceHeader{
+					Name:  name,
+					Type:  TypeAAAA,
+					Class: ClassINET,
+				},
+				&AAAAResource{[16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}},
+			},
+			{
+				ResourceHeader{
+					Name:  name,
+					Type:  TypeCNAME,
+					Class: ClassINET,
+				},
+				&CNAMEResource{mustNewName("alias.example.com.")},
+			},
+			{
+				ResourceHeader{
+					Name:  name,
+					Type:  TypeSOA,
+					Class: ClassINET,
+				},
+				&SOAResource{
+					NS:      mustNewName("ns1.example.com."),
+					MBox:    mustNewName("mb.example.com."),
+					Serial:  1,
+					Refresh: 2,
+					Retry:   3,
+					Expire:  4,
+					MinTTL:  5,
+				},
+			},
+			{
+				ResourceHeader{
+					Name:  name,
+					Type:  TypePTR,
+					Class: ClassINET,
+				},
+				&PTRResource{mustNewName("ptr.example.com.")},
+			},
+			{
+				ResourceHeader{
+					Name:  name,
+					Type:  TypeMX,
+					Class: ClassINET,
+				},
+				&MXResource{
+					7,
+					mustNewName("mx.example.com."),
+				},
+			},
+			{
+				ResourceHeader{
+					Name:  name,
+					Type:  TypeSRV,
+					Class: ClassINET,
+				},
+				&SRVResource{
+					8,
+					9,
+					11,
+					mustNewName("srv.example.com."),
+				},
 			},
 			},
 		},
 		},
 		Authorities: []Resource{
 		Authorities: []Resource{
-			&NSResource{
-				ResourceHeader: ResourceHeader{
-					Name:  "foo.bar.example.com.",
+			{
+				ResourceHeader{
+					Name:  name,
 					Type:  TypeNS,
 					Type:  TypeNS,
 					Class: ClassINET,
 					Class: ClassINET,
 				},
 				},
-				NS: "ns1.example.com.",
+				&NSResource{mustNewName("ns1.example.com.")},
 			},
 			},
-			&NSResource{
-				ResourceHeader: ResourceHeader{
-					Name:  "foo.bar.example.com.",
+			{
+				ResourceHeader{
+					Name:  name,
 					Type:  TypeNS,
 					Type:  TypeNS,
 					Class: ClassINET,
 					Class: ClassINET,
 				},
 				},
-				NS: "ns2.example.com.",
+				&NSResource{mustNewName("ns2.example.com.")},
 			},
 			},
 		},
 		},
 		Additionals: []Resource{
 		Additionals: []Resource{
-			&TXTResource{
-				ResourceHeader: ResourceHeader{
-					Name:  "foo.bar.example.com.",
+			{
+				ResourceHeader{
+					Name:  name,
 					Type:  TypeTXT,
 					Type:  TypeTXT,
 					Class: ClassINET,
 					Class: ClassINET,
 				},
 				},
-				Txt: "So Long, and Thanks for All the Fish",
+				&TXTResource{[]string{"So Long, and Thanks for All the Fish"}},
 			},
 			},
-			&TXTResource{
-				ResourceHeader: ResourceHeader{
-					Name:  "foo.bar.example.com.",
+			{
+				ResourceHeader{
+					Name:  name,
 					Type:  TypeTXT,
 					Type:  TypeTXT,
 					Class: ClassINET,
 					Class: ClassINET,
 				},
 				},
-				Txt: "Hamster Huey and the Gooey Kablooie",
+				&TXTResource{[]string{"Hamster Huey and the Gooey Kablooie"}},
+			},
+			{
+				mustEDNS0ResourceHeader(4096, 0xfe0|RCodeSuccess, false),
+				&OPTResource{
+					Options: []Option{
+						{
+							Code: 10, // see RFC 7873
+							Data: []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
+						},
+					},
+				},
 			},
 			},
 		},
 		},
 	}
 	}
 }
 }
-
-const loremIpsum = `
-Lorem ipsum dolor sit amet, nec enim antiopam id, an ullum choro
-nonumes qui, pro eu debet honestatis mediocritatem. No alia enim eos,
-magna signiferumque ex vis. Mei no aperiri dissentias, cu vel quas
-regione. Malorum quaeque vim ut, eum cu semper aliquid invidunt, ei
-nam ipsum assentior.
-
-Nostrum appellantur usu no, vis ex probatus adipiscing. Cu usu illum
-facilis eleifend. Iusto conceptam complectitur vim id. Tale omnesque
-no usu, ei oblique sadipscing vim. At nullam voluptua usu, mei laudem
-reformidans et. Qui ei eros porro reformidans, ius suas veritus
-torquatos ex. Mea te facer alterum consequat.
-
-Soleat torquatos democritum sed et, no mea congue appareat, facer
-aliquam nec in. Has te ipsum tritani. At justo dicta option nec, movet
-phaedrum ad nam. Ea detracto verterem liberavisse has, delectus
-suscipiantur in mei. Ex nam meliore complectitur. Ut nam omnis
-honestatis quaerendum, ea mea nihil affert detracto, ad vix rebum
-mollis.
-
-Ut epicurei praesent neglegentur pri, prima fuisset intellegebat ad
-vim. An habemus comprehensam usu, at enim dignissim pro. Eam reque
-vivendum adipisci ea. Vel ne odio choro minimum. Sea admodum
-dissentiet ex. Mundi tamquam evertitur ius cu. Homero postea iisque ut
-pro, vel ne saepe senserit consetetur.
-
-Nulla utamur facilisis ius ea, in viderer diceret pertinax eum. Mei no
-enim quodsi facilisi, ex sed aeterno appareat mediocritatem, eum
-sententiae deterruisset ut. At suas timeam euismod cum, offendit
-appareat interpretaris ne vix. Vel ea civibus albucius, ex vim quidam
-accusata intellegebat, noluisse instructior sea id. Nec te nonumes
-habemus appellantur, quis dignissim vituperata eu nam.
-
-At vix apeirian patrioque vituperatoribus, an usu agam assum. Debet
-iisque an mea. Per eu dicant ponderum accommodare. Pri alienum
-placerat senserit an, ne eum ferri abhorreant vituperatoribus. Ut mea
-eligendi disputationi. Ius no tation everti impedit, ei magna quidam
-mediocritatem pri.
-
-Legendos perpetua iracundia ne usu, no ius ullum epicurei intellegam,
-ad modus epicuri lucilius eam. In unum quaerendum usu. Ne diam paulo
-has, ea veri virtute sed. Alia honestatis conclusionemque mea eu, ut
-iudico albucius his.
-
-Usu essent probatus eu, sed omnis dolor delicatissimi ex. No qui augue
-dissentias dissentiet. Laudem recteque no usu, vel an velit noluisse,
-an sed utinam eirmod appetere. Ne mea fuisset inimicus ocurreret. At
-vis dicant abhorreant, utinam forensibus nec ne, mei te docendi
-consequat. Brute inermis persecuti cum id. Ut ipsum munere propriae
-usu, dicit graeco disputando id has.
-
-Eros dolore quaerendum nam ei. Timeam ornatus inciderint pro id. Nec
-torquatos sadipscing ei, ancillae molestie per in. Malis principes duo
-ea, usu liber postulant ei.
-
-Graece timeam voluptatibus eu eam. Alia probatus quo no, ea scripta
-feugiat duo. Congue option meliore ex qui, noster invenire appellantur
-ea vel. Eu exerci legendos vel. Consetetur repudiandae vim ut. Vix an
-probo minimum, et nam illud falli tempor.
-
-Cum dico signiferumque eu. Sed ut regione maiorum, id veritus insolens
-tacimates vix. Eu mel sint tamquam lucilius, duo no oporteat
-tacimates. Atqui augue concludaturque vix ei, id mel utroque menandri.
-
-Ad oratio blandit aliquando pro. Vis et dolorum rationibus
-philosophia, ad cum nulla molestie. Hinc fuisset adversarium eum et,
-ne qui nisl verear saperet, vel te quaestio forensibus. Per odio
-option delenit an. Alii placerat has no, in pri nihil platonem
-cotidieque. Est ut elit copiosae scaevola, debet tollit maluisset sea
-an.
-
-Te sea hinc debet pericula, liber ridens fabulas cu sed, quem mutat
-accusam mea et. Elitr labitur albucius et pri, an labore feugait mel.
-Velit zril melius usu ea. Ad stet putent interpretaris qui. Mel no
-error volumus scripserit. In pro paulo iudico, quo ei dolorem
-verterem, affert fabellas dissentiet ea vix.
-
-Vis quot deserunt te. Error aliquid detraxit eu usu, vis alia eruditi
-salutatus cu. Est nostrud bonorum an, ei usu alii salutatus. Vel at
-nisl primis, eum ex aperiri noluisse reformidans. Ad veri velit
-utroque vis, ex equidem detraxit temporibus has.
-
-Inermis appareat usu ne. Eros placerat periculis mea ad, in dictas
-pericula pro. Errem postulant at usu, ea nec amet ornatus mentitum. Ad
-mazim graeco eum, vel ex percipit volutpat iudicabit, sit ne delicata
-interesset. Mel sapientem prodesset abhorreant et, oblique suscipit
-eam id.
-
-An maluisset disputando mea, vidit mnesarchum pri et. Malis insolens
-inciderint no sea. Ea persius maluisset vix, ne vim appellantur
-instructior, consul quidam definiebas pri id. Cum integre feugiat
-pericula in, ex sed persius similique, mel ne natum dicit percipitur.
-
-Primis discere ne pri, errem putent definitionem at vis. Ei mel dolore
-neglegentur, mei tincidunt percipitur ei. Pro ad simul integre
-rationibus. Eu vel alii honestatis definitiones, mea no nonumy
-reprehendunt.
-
-Dicta appareat legendos est cu. Eu vel congue dicunt omittam, no vix
-adhuc minimum constituam, quot noluisse id mel. Eu quot sale mutat
-duo, ex nisl munere invenire duo. Ne nec ullum utamur. Pro alterum
-debitis nostrum no, ut vel aliquid vivendo.
-
-Aliquip fierent praesent quo ne, id sit audiam recusabo delicatissimi.
-Usu postulant incorrupte cu. At pro dicit tibique intellegam, cibo
-dolore impedit id eam, et aeque feugait assentior has. Quando sensibus
-nec ex. Possit sensibus pri ad, unum mutat periculis cu vix.
-
-Mundi tibique vix te, duo simul partiendo qualisque id, est at vidit
-sonet tempor. No per solet aeterno deseruisse. Petentium salutandi
-definiebas pri cu. Munere vivendum est in. Ei justo congue eligendi
-vis, modus offendit omittantur te mel.
-
-Integre voluptaria in qui, sit habemus tractatos constituam no. Utinam
-melius conceptam est ne, quo in minimum apeirian delicata, ut ius
-porro recusabo. Dicant expetenda vix no, ludus scripserit sed ex, eu
-his modo nostro. Ut etiam sonet his, quodsi inciderint philosophia te
-per. Nullam lobortis eu cum, vix an sonet efficiendi repudiandae. Vis
-ad idque fabellas intellegebat.
-
-Eum commodo senserit conclusionemque ex. Sed forensibus sadipscing ut,
-mei in facer delicata periculis, sea ne hinc putent cetero. Nec ne
-alia corpora invenire, alia prima soleat te cum. Eleifend posidonium
-nam at.
-
-Dolorum indoctum cu quo, ex dolor legendos recteque eam, cu pri zril
-discere. Nec civibus officiis dissentiunt ex, est te liber ludus
-elaboraret. Cum ea fabellas invenire. Ex vim nostrud eripuit
-comprehensam, nam te inermis delectus, saepe inermis senserit.
-`

+ 101 - 37
vendor/golang.org/x/net/html/atom/gen.go

@@ -4,17 +4,17 @@
 
 
 // +build ignore
 // +build ignore
 
 
-package main
+//go:generate go run gen.go
+//go:generate go run gen.go -test
 
 
-// This program generates table.go and table_test.go.
-// Invoke as
-//
-//	go run gen.go |gofmt >table.go
-//	go run gen.go -test |gofmt >table_test.go
+package main
 
 
 import (
 import (
+	"bytes"
 	"flag"
 	"flag"
 	"fmt"
 	"fmt"
+	"go/format"
+	"io/ioutil"
 	"math/rand"
 	"math/rand"
 	"os"
 	"os"
 	"sort"
 	"sort"
@@ -42,6 +42,18 @@ func identifier(s string) string {
 
 
 var test = flag.Bool("test", false, "generate table_test.go")
 var test = flag.Bool("test", false, "generate table_test.go")
 
 
+func genFile(name string, buf *bytes.Buffer) {
+	b, err := format.Source(buf.Bytes())
+	if err != nil {
+		fmt.Fprintln(os.Stderr, err)
+		os.Exit(1)
+	}
+	if err := ioutil.WriteFile(name, b, 0644); err != nil {
+		fmt.Fprintln(os.Stderr, err)
+		os.Exit(1)
+	}
+}
+
 func main() {
 func main() {
 	flag.Parse()
 	flag.Parse()
 
 
@@ -52,32 +64,31 @@ func main() {
 	all = append(all, extra...)
 	all = append(all, extra...)
 	sort.Strings(all)
 	sort.Strings(all)
 
 
-	if *test {
-		fmt.Printf("// generated by go run gen.go -test; DO NOT EDIT\n\n")
-		fmt.Printf("package atom\n\n")
-		fmt.Printf("var testAtomList = []string{\n")
-		for _, s := range all {
-			fmt.Printf("\t%q,\n", s)
-		}
-		fmt.Printf("}\n")
-		return
-	}
-
 	// uniq - lists have dups
 	// uniq - lists have dups
-	// compute max len too
-	maxLen := 0
 	w := 0
 	w := 0
 	for _, s := range all {
 	for _, s := range all {
 		if w == 0 || all[w-1] != s {
 		if w == 0 || all[w-1] != s {
-			if maxLen < len(s) {
-				maxLen = len(s)
-			}
 			all[w] = s
 			all[w] = s
 			w++
 			w++
 		}
 		}
 	}
 	}
 	all = all[:w]
 	all = all[:w]
 
 
+	if *test {
+		var buf bytes.Buffer
+		fmt.Fprintln(&buf, "// Code generated by go generate gen.go; DO NOT EDIT.\n")
+		fmt.Fprintln(&buf, "//go:generate go run gen.go -test\n")
+		fmt.Fprintln(&buf, "package atom\n")
+		fmt.Fprintln(&buf, "var testAtomList = []string{")
+		for _, s := range all {
+			fmt.Fprintf(&buf, "\t%q,\n", s)
+		}
+		fmt.Fprintln(&buf, "}")
+
+		genFile("table_test.go", &buf)
+		return
+	}
+
 	// Find hash that minimizes table size.
 	// Find hash that minimizes table size.
 	var best *table
 	var best *table
 	for i := 0; i < 1000000; i++ {
 	for i := 0; i < 1000000; i++ {
@@ -163,36 +174,46 @@ func main() {
 		atom[s] = uint32(off<<8 | len(s))
 		atom[s] = uint32(off<<8 | len(s))
 	}
 	}
 
 
+	var buf bytes.Buffer
 	// Generate the Go code.
 	// Generate the Go code.
-	fmt.Printf("// generated by go run gen.go; DO NOT EDIT\n\n")
-	fmt.Printf("package atom\n\nconst (\n")
+	fmt.Fprintln(&buf, "// Code generated by go generate gen.go; DO NOT EDIT.\n")
+	fmt.Fprintln(&buf, "//go:generate go run gen.go\n")
+	fmt.Fprintln(&buf, "package atom\n\nconst (")
+
+	// compute max len
+	maxLen := 0
 	for _, s := range all {
 	for _, s := range all {
-		fmt.Printf("\t%s Atom = %#x\n", identifier(s), atom[s])
+		if maxLen < len(s) {
+			maxLen = len(s)
+		}
+		fmt.Fprintf(&buf, "\t%s Atom = %#x\n", identifier(s), atom[s])
 	}
 	}
-	fmt.Printf(")\n\n")
+	fmt.Fprintln(&buf, ")\n")
 
 
-	fmt.Printf("const hash0 = %#x\n\n", best.h0)
-	fmt.Printf("const maxAtomLen = %d\n\n", maxLen)
+	fmt.Fprintf(&buf, "const hash0 = %#x\n\n", best.h0)
+	fmt.Fprintf(&buf, "const maxAtomLen = %d\n\n", maxLen)
 
 
-	fmt.Printf("var table = [1<<%d]Atom{\n", best.k)
+	fmt.Fprintf(&buf, "var table = [1<<%d]Atom{\n", best.k)
 	for i, s := range best.tab {
 	for i, s := range best.tab {
 		if s == "" {
 		if s == "" {
 			continue
 			continue
 		}
 		}
-		fmt.Printf("\t%#x: %#x, // %s\n", i, atom[s], s)
+		fmt.Fprintf(&buf, "\t%#x: %#x, // %s\n", i, atom[s], s)
 	}
 	}
-	fmt.Printf("}\n")
+	fmt.Fprintf(&buf, "}\n")
 	datasize := (1 << best.k) * 4
 	datasize := (1 << best.k) * 4
 
 
-	fmt.Printf("const atomText =\n")
+	fmt.Fprintln(&buf, "const atomText =")
 	textsize := len(text)
 	textsize := len(text)
 	for len(text) > 60 {
 	for len(text) > 60 {
-		fmt.Printf("\t%q +\n", text[:60])
+		fmt.Fprintf(&buf, "\t%q +\n", text[:60])
 		text = text[60:]
 		text = text[60:]
 	}
 	}
-	fmt.Printf("\t%q\n\n", text)
+	fmt.Fprintf(&buf, "\t%q\n\n", text)
+
+	genFile("table.go", &buf)
 
 
-	fmt.Fprintf(os.Stderr, "%d atoms; %d string bytes + %d tables = %d total data\n", len(all), textsize, datasize, textsize+datasize)
+	fmt.Fprintf(os.Stdout, "%d atoms; %d string bytes + %d tables = %d total data\n", len(all), textsize, datasize, textsize+datasize)
 }
 }
 
 
 type byLen []string
 type byLen []string
@@ -285,8 +306,10 @@ func (t *table) push(i uint32, depth int) bool {
 
 
 // The lists of element names and attribute keys were taken from
 // The lists of element names and attribute keys were taken from
 // https://html.spec.whatwg.org/multipage/indices.html#index
 // https://html.spec.whatwg.org/multipage/indices.html#index
-// as of the "HTML Living Standard - Last Updated 21 February 2015" version.
+// as of the "HTML Living Standard - Last Updated 16 April 2018" version.
 
 
+// "command", "keygen" and "menuitem" have been removed from the spec,
+// but are kept here for backwards compatibility.
 var elements = []string{
 var elements = []string{
 	"a",
 	"a",
 	"abbr",
 	"abbr",
@@ -349,6 +372,7 @@ var elements = []string{
 	"legend",
 	"legend",
 	"li",
 	"li",
 	"link",
 	"link",
+	"main",
 	"map",
 	"map",
 	"mark",
 	"mark",
 	"menu",
 	"menu",
@@ -364,6 +388,7 @@ var elements = []string{
 	"output",
 	"output",
 	"p",
 	"p",
 	"param",
 	"param",
+	"picture",
 	"pre",
 	"pre",
 	"progress",
 	"progress",
 	"q",
 	"q",
@@ -375,6 +400,7 @@ var elements = []string{
 	"script",
 	"script",
 	"section",
 	"section",
 	"select",
 	"select",
+	"slot",
 	"small",
 	"small",
 	"source",
 	"source",
 	"span",
 	"span",
@@ -403,14 +429,21 @@ var elements = []string{
 }
 }
 
 
 // https://html.spec.whatwg.org/multipage/indices.html#attributes-3
 // https://html.spec.whatwg.org/multipage/indices.html#attributes-3
-
+//
+// "challenge", "command", "contextmenu", "dropzone", "icon", "keytype", "mediagroup",
+// "radiogroup", "spellcheck", "scoped", "seamless", "sortable" and "sorted" have been removed from the spec,
+// but are kept here for backwards compatibility.
 var attributes = []string{
 var attributes = []string{
 	"abbr",
 	"abbr",
 	"accept",
 	"accept",
 	"accept-charset",
 	"accept-charset",
 	"accesskey",
 	"accesskey",
 	"action",
 	"action",
+	"allowfullscreen",
+	"allowpaymentrequest",
+	"allowusermedia",
 	"alt",
 	"alt",
+	"as",
 	"async",
 	"async",
 	"autocomplete",
 	"autocomplete",
 	"autofocus",
 	"autofocus",
@@ -420,6 +453,7 @@ var attributes = []string{
 	"checked",
 	"checked",
 	"cite",
 	"cite",
 	"class",
 	"class",
+	"color",
 	"cols",
 	"cols",
 	"colspan",
 	"colspan",
 	"command",
 	"command",
@@ -457,6 +491,8 @@ var attributes = []string{
 	"icon",
 	"icon",
 	"id",
 	"id",
 	"inputmode",
 	"inputmode",
+	"integrity",
+	"is",
 	"ismap",
 	"ismap",
 	"itemid",
 	"itemid",
 	"itemprop",
 	"itemprop",
@@ -481,16 +517,20 @@ var attributes = []string{
 	"multiple",
 	"multiple",
 	"muted",
 	"muted",
 	"name",
 	"name",
+	"nomodule",
+	"nonce",
 	"novalidate",
 	"novalidate",
 	"open",
 	"open",
 	"optimum",
 	"optimum",
 	"pattern",
 	"pattern",
 	"ping",
 	"ping",
 	"placeholder",
 	"placeholder",
+	"playsinline",
 	"poster",
 	"poster",
 	"preload",
 	"preload",
 	"radiogroup",
 	"radiogroup",
 	"readonly",
 	"readonly",
+	"referrerpolicy",
 	"rel",
 	"rel",
 	"required",
 	"required",
 	"reversed",
 	"reversed",
@@ -507,10 +547,13 @@ var attributes = []string{
 	"sizes",
 	"sizes",
 	"sortable",
 	"sortable",
 	"sorted",
 	"sorted",
+	"slot",
 	"span",
 	"span",
+	"spellcheck",
 	"src",
 	"src",
 	"srcdoc",
 	"srcdoc",
 	"srclang",
 	"srclang",
+	"srcset",
 	"start",
 	"start",
 	"step",
 	"step",
 	"style",
 	"style",
@@ -520,16 +563,22 @@ var attributes = []string{
 	"translate",
 	"translate",
 	"type",
 	"type",
 	"typemustmatch",
 	"typemustmatch",
+	"updateviacache",
 	"usemap",
 	"usemap",
 	"value",
 	"value",
 	"width",
 	"width",
+	"workertype",
 	"wrap",
 	"wrap",
 }
 }
 
 
+// "onautocomplete", "onautocompleteerror", "onmousewheel",
+// "onshow" and "onsort" have been removed from the spec,
+// but are kept here for backwards compatibility.
 var eventHandlers = []string{
 var eventHandlers = []string{
 	"onabort",
 	"onabort",
 	"onautocomplete",
 	"onautocomplete",
 	"onautocompleteerror",
 	"onautocompleteerror",
+	"onauxclick",
 	"onafterprint",
 	"onafterprint",
 	"onbeforeprint",
 	"onbeforeprint",
 	"onbeforeunload",
 	"onbeforeunload",
@@ -541,11 +590,14 @@ var eventHandlers = []string{
 	"onclick",
 	"onclick",
 	"onclose",
 	"onclose",
 	"oncontextmenu",
 	"oncontextmenu",
+	"oncopy",
 	"oncuechange",
 	"oncuechange",
+	"oncut",
 	"ondblclick",
 	"ondblclick",
 	"ondrag",
 	"ondrag",
 	"ondragend",
 	"ondragend",
 	"ondragenter",
 	"ondragenter",
+	"ondragexit",
 	"ondragleave",
 	"ondragleave",
 	"ondragover",
 	"ondragover",
 	"ondragstart",
 	"ondragstart",
@@ -565,18 +617,24 @@ var eventHandlers = []string{
 	"onload",
 	"onload",
 	"onloadeddata",
 	"onloadeddata",
 	"onloadedmetadata",
 	"onloadedmetadata",
+	"onloadend",
 	"onloadstart",
 	"onloadstart",
 	"onmessage",
 	"onmessage",
+	"onmessageerror",
 	"onmousedown",
 	"onmousedown",
+	"onmouseenter",
+	"onmouseleave",
 	"onmousemove",
 	"onmousemove",
 	"onmouseout",
 	"onmouseout",
 	"onmouseover",
 	"onmouseover",
 	"onmouseup",
 	"onmouseup",
 	"onmousewheel",
 	"onmousewheel",
+	"onwheel",
 	"onoffline",
 	"onoffline",
 	"ononline",
 	"ononline",
 	"onpagehide",
 	"onpagehide",
 	"onpageshow",
 	"onpageshow",
+	"onpaste",
 	"onpause",
 	"onpause",
 	"onplay",
 	"onplay",
 	"onplaying",
 	"onplaying",
@@ -585,7 +643,9 @@ var eventHandlers = []string{
 	"onratechange",
 	"onratechange",
 	"onreset",
 	"onreset",
 	"onresize",
 	"onresize",
+	"onrejectionhandled",
 	"onscroll",
 	"onscroll",
+	"onsecuritypolicyviolation",
 	"onseeked",
 	"onseeked",
 	"onseeking",
 	"onseeking",
 	"onselect",
 	"onselect",
@@ -597,6 +657,7 @@ var eventHandlers = []string{
 	"onsuspend",
 	"onsuspend",
 	"ontimeupdate",
 	"ontimeupdate",
 	"ontoggle",
 	"ontoggle",
+	"onunhandledrejection",
 	"onunload",
 	"onunload",
 	"onvolumechange",
 	"onvolumechange",
 	"onwaiting",
 	"onwaiting",
@@ -604,6 +665,7 @@ var eventHandlers = []string{
 
 
 // extra are ad-hoc values not covered by any of the lists above.
 // extra are ad-hoc values not covered by any of the lists above.
 var extra = []string{
 var extra = []string{
+	"acronym",
 	"align",
 	"align",
 	"annotation",
 	"annotation",
 	"annotation-xml",
 	"annotation-xml",
@@ -639,6 +701,8 @@ var extra = []string{
 	"plaintext",
 	"plaintext",
 	"prompt",
 	"prompt",
 	"public",
 	"public",
+	"rb",
+	"rtc",
 	"spacer",
 	"spacer",
 	"strike",
 	"strike",
 	"svg",
 	"svg",

+ 772 - 702
vendor/golang.org/x/net/html/atom/table.go

@@ -1,713 +1,783 @@
-// generated by go run gen.go; DO NOT EDIT
+// Code generated by go generate gen.go; DO NOT EDIT.
+
+//go:generate go run gen.go
 
 
 package atom
 package atom
 
 
 const (
 const (
-	A                   Atom = 0x1
-	Abbr                Atom = 0x4
-	Accept              Atom = 0x2106
-	AcceptCharset       Atom = 0x210e
-	Accesskey           Atom = 0x3309
-	Action              Atom = 0x1f606
-	Address             Atom = 0x4f307
-	Align               Atom = 0x1105
-	Alt                 Atom = 0x4503
-	Annotation          Atom = 0x1670a
-	AnnotationXml       Atom = 0x1670e
-	Applet              Atom = 0x2b306
-	Area                Atom = 0x2fa04
-	Article             Atom = 0x38807
-	Aside               Atom = 0x8305
-	Async               Atom = 0x7b05
-	Audio               Atom = 0xa605
-	Autocomplete        Atom = 0x1fc0c
-	Autofocus           Atom = 0xb309
-	Autoplay            Atom = 0xce08
-	B                   Atom = 0x101
-	Base                Atom = 0xd604
-	Basefont            Atom = 0xd608
-	Bdi                 Atom = 0x1a03
-	Bdo                 Atom = 0xe703
-	Bgsound             Atom = 0x11807
-	Big                 Atom = 0x12403
-	Blink               Atom = 0x12705
-	Blockquote          Atom = 0x12c0a
-	Body                Atom = 0x2f04
-	Br                  Atom = 0x202
-	Button              Atom = 0x13606
-	Canvas              Atom = 0x7f06
-	Caption             Atom = 0x1bb07
-	Center              Atom = 0x5b506
-	Challenge           Atom = 0x21f09
-	Charset             Atom = 0x2807
-	Checked             Atom = 0x32807
-	Cite                Atom = 0x3c804
-	Class               Atom = 0x4de05
-	Code                Atom = 0x14904
-	Col                 Atom = 0x15003
-	Colgroup            Atom = 0x15008
-	Color               Atom = 0x15d05
-	Cols                Atom = 0x16204
-	Colspan             Atom = 0x16207
-	Command             Atom = 0x17507
-	Content             Atom = 0x42307
-	Contenteditable     Atom = 0x4230f
-	Contextmenu         Atom = 0x3310b
-	Controls            Atom = 0x18808
-	Coords              Atom = 0x19406
-	Crossorigin         Atom = 0x19f0b
-	Data                Atom = 0x44a04
-	Datalist            Atom = 0x44a08
-	Datetime            Atom = 0x23c08
-	Dd                  Atom = 0x26702
-	Default             Atom = 0x8607
-	Defer               Atom = 0x14b05
-	Del                 Atom = 0x3ef03
-	Desc                Atom = 0x4db04
-	Details             Atom = 0x4807
-	Dfn                 Atom = 0x6103
-	Dialog              Atom = 0x1b06
-	Dir                 Atom = 0x6903
-	Dirname             Atom = 0x6907
-	Disabled            Atom = 0x10c08
-	Div                 Atom = 0x11303
-	Dl                  Atom = 0x11e02
-	Download            Atom = 0x40008
-	Draggable           Atom = 0x17b09
-	Dropzone            Atom = 0x39108
-	Dt                  Atom = 0x50902
-	Em                  Atom = 0x6502
-	Embed               Atom = 0x6505
-	Enctype             Atom = 0x21107
-	Face                Atom = 0x5b304
-	Fieldset            Atom = 0x1b008
-	Figcaption          Atom = 0x1b80a
-	Figure              Atom = 0x1cc06
-	Font                Atom = 0xda04
-	Footer              Atom = 0x8d06
-	For                 Atom = 0x1d803
-	ForeignObject       Atom = 0x1d80d
-	Foreignobject       Atom = 0x1e50d
-	Form                Atom = 0x1f204
-	Formaction          Atom = 0x1f20a
-	Formenctype         Atom = 0x20d0b
-	Formmethod          Atom = 0x2280a
-	Formnovalidate      Atom = 0x2320e
-	Formtarget          Atom = 0x2470a
-	Frame               Atom = 0x9a05
-	Frameset            Atom = 0x9a08
-	H1                  Atom = 0x26e02
-	H2                  Atom = 0x29402
-	H3                  Atom = 0x2a702
-	H4                  Atom = 0x2e902
-	H5                  Atom = 0x2f302
-	H6                  Atom = 0x50b02
-	Head                Atom = 0x2d504
-	Header              Atom = 0x2d506
-	Headers             Atom = 0x2d507
-	Height              Atom = 0x25106
-	Hgroup              Atom = 0x25906
-	Hidden              Atom = 0x26506
-	High                Atom = 0x26b04
-	Hr                  Atom = 0x27002
-	Href                Atom = 0x27004
-	Hreflang            Atom = 0x27008
-	Html                Atom = 0x25504
-	HttpEquiv           Atom = 0x2780a
-	I                   Atom = 0x601
-	Icon                Atom = 0x42204
-	Id                  Atom = 0x8502
-	Iframe              Atom = 0x29606
-	Image               Atom = 0x29c05
-	Img                 Atom = 0x2a103
-	Input               Atom = 0x3e805
-	Inputmode           Atom = 0x3e809
-	Ins                 Atom = 0x1a803
-	Isindex             Atom = 0x2a907
-	Ismap               Atom = 0x2b005
-	Itemid              Atom = 0x33c06
-	Itemprop            Atom = 0x3c908
-	Itemref             Atom = 0x5ad07
-	Itemscope           Atom = 0x2b909
-	Itemtype            Atom = 0x2c308
-	Kbd                 Atom = 0x1903
-	Keygen              Atom = 0x3906
-	Keytype             Atom = 0x53707
-	Kind                Atom = 0x10904
-	Label               Atom = 0xf005
-	Lang                Atom = 0x27404
-	Legend              Atom = 0x18206
-	Li                  Atom = 0x1202
-	Link                Atom = 0x12804
-	List                Atom = 0x44e04
-	Listing             Atom = 0x44e07
-	Loop                Atom = 0xf404
-	Low                 Atom = 0x11f03
-	Malignmark          Atom = 0x100a
-	Manifest            Atom = 0x5f108
-	Map                 Atom = 0x2b203
-	Mark                Atom = 0x1604
-	Marquee             Atom = 0x2cb07
-	Math                Atom = 0x2d204
-	Max                 Atom = 0x2e103
-	Maxlength           Atom = 0x2e109
-	Media               Atom = 0x6e05
-	Mediagroup          Atom = 0x6e0a
-	Menu                Atom = 0x33804
-	Menuitem            Atom = 0x33808
-	Meta                Atom = 0x45d04
-	Meter               Atom = 0x24205
-	Method              Atom = 0x22c06
-	Mglyph              Atom = 0x2a206
-	Mi                  Atom = 0x2eb02
-	Min                 Atom = 0x2eb03
-	Minlength           Atom = 0x2eb09
-	Mn                  Atom = 0x23502
-	Mo                  Atom = 0x3ed02
-	Ms                  Atom = 0x2bc02
-	Mtext               Atom = 0x2f505
-	Multiple            Atom = 0x30308
-	Muted               Atom = 0x30b05
-	Name                Atom = 0x6c04
-	Nav                 Atom = 0x3e03
-	Nobr                Atom = 0x5704
-	Noembed             Atom = 0x6307
-	Noframes            Atom = 0x9808
-	Noscript            Atom = 0x3d208
-	Novalidate          Atom = 0x2360a
-	Object              Atom = 0x1ec06
-	Ol                  Atom = 0xc902
-	Onabort             Atom = 0x13a07
-	Onafterprint        Atom = 0x1c00c
-	Onautocomplete      Atom = 0x1fa0e
-	Onautocompleteerror Atom = 0x1fa13
-	Onbeforeprint       Atom = 0x6040d
-	Onbeforeunload      Atom = 0x4e70e
-	Onblur              Atom = 0xaa06
-	Oncancel            Atom = 0xe908
-	Oncanplay           Atom = 0x28509
-	Oncanplaythrough    Atom = 0x28510
-	Onchange            Atom = 0x3a708
-	Onclick             Atom = 0x31007
-	Onclose             Atom = 0x31707
-	Oncontextmenu       Atom = 0x32f0d
-	Oncuechange         Atom = 0x3420b
-	Ondblclick          Atom = 0x34d0a
-	Ondrag              Atom = 0x35706
-	Ondragend           Atom = 0x35709
-	Ondragenter         Atom = 0x3600b
-	Ondragleave         Atom = 0x36b0b
-	Ondragover          Atom = 0x3760a
-	Ondragstart         Atom = 0x3800b
-	Ondrop              Atom = 0x38f06
-	Ondurationchange    Atom = 0x39f10
-	Onemptied           Atom = 0x39609
-	Onended             Atom = 0x3af07
-	Onerror             Atom = 0x3b607
-	Onfocus             Atom = 0x3bd07
-	Onhashchange        Atom = 0x3da0c
-	Oninput             Atom = 0x3e607
-	Oninvalid           Atom = 0x3f209
-	Onkeydown           Atom = 0x3fb09
-	Onkeypress          Atom = 0x4080a
-	Onkeyup             Atom = 0x41807
-	Onlanguagechange    Atom = 0x43210
-	Onload              Atom = 0x44206
-	Onloadeddata        Atom = 0x4420c
-	Onloadedmetadata    Atom = 0x45510
-	Onloadstart         Atom = 0x46b0b
-	Onmessage           Atom = 0x47609
-	Onmousedown         Atom = 0x47f0b
-	Onmousemove         Atom = 0x48a0b
-	Onmouseout          Atom = 0x4950a
-	Onmouseover         Atom = 0x4a20b
-	Onmouseup           Atom = 0x4ad09
-	Onmousewheel        Atom = 0x4b60c
-	Onoffline           Atom = 0x4c209
-	Ononline            Atom = 0x4cb08
-	Onpagehide          Atom = 0x4d30a
-	Onpageshow          Atom = 0x4fe0a
-	Onpause             Atom = 0x50d07
-	Onplay              Atom = 0x51706
-	Onplaying           Atom = 0x51709
-	Onpopstate          Atom = 0x5200a
-	Onprogress          Atom = 0x52a0a
-	Onratechange        Atom = 0x53e0c
-	Onreset             Atom = 0x54a07
-	Onresize            Atom = 0x55108
-	Onscroll            Atom = 0x55f08
-	Onseeked            Atom = 0x56708
-	Onseeking           Atom = 0x56f09
-	Onselect            Atom = 0x57808
-	Onshow              Atom = 0x58206
-	Onsort              Atom = 0x58b06
-	Onstalled           Atom = 0x59509
-	Onstorage           Atom = 0x59e09
-	Onsubmit            Atom = 0x5a708
-	Onsuspend           Atom = 0x5bb09
-	Ontimeupdate        Atom = 0xdb0c
-	Ontoggle            Atom = 0x5c408
-	Onunload            Atom = 0x5cc08
-	Onvolumechange      Atom = 0x5d40e
-	Onwaiting           Atom = 0x5e209
-	Open                Atom = 0x3cf04
-	Optgroup            Atom = 0xf608
-	Optimum             Atom = 0x5eb07
-	Option              Atom = 0x60006
-	Output              Atom = 0x49c06
-	P                   Atom = 0xc01
-	Param               Atom = 0xc05
-	Pattern             Atom = 0x5107
-	Ping                Atom = 0x7704
-	Placeholder         Atom = 0xc30b
-	Plaintext           Atom = 0xfd09
-	Poster              Atom = 0x15706
-	Pre                 Atom = 0x25e03
-	Preload             Atom = 0x25e07
-	Progress            Atom = 0x52c08
-	Prompt              Atom = 0x5fa06
-	Public              Atom = 0x41e06
-	Q                   Atom = 0x13101
-	Radiogroup          Atom = 0x30a
-	Readonly            Atom = 0x2fb08
-	Rel                 Atom = 0x25f03
-	Required            Atom = 0x1d008
-	Reversed            Atom = 0x5a08
-	Rows                Atom = 0x9204
-	Rowspan             Atom = 0x9207
-	Rp                  Atom = 0x1c602
-	Rt                  Atom = 0x13f02
-	Ruby                Atom = 0xaf04
-	S                   Atom = 0x2c01
-	Samp                Atom = 0x4e04
-	Sandbox             Atom = 0xbb07
-	Scope               Atom = 0x2bd05
-	Scoped              Atom = 0x2bd06
-	Script              Atom = 0x3d406
-	Seamless            Atom = 0x31c08
-	Section             Atom = 0x4e207
-	Select              Atom = 0x57a06
-	Selected            Atom = 0x57a08
-	Shape               Atom = 0x4f905
-	Size                Atom = 0x55504
-	Sizes               Atom = 0x55505
-	Small               Atom = 0x18f05
-	Sortable            Atom = 0x58d08
-	Sorted              Atom = 0x19906
-	Source              Atom = 0x1aa06
-	Spacer              Atom = 0x2db06
-	Span                Atom = 0x9504
-	Spellcheck          Atom = 0x3230a
-	Src                 Atom = 0x3c303
-	Srcdoc              Atom = 0x3c306
-	Srclang             Atom = 0x41107
-	Start               Atom = 0x38605
-	Step                Atom = 0x5f704
-	Strike              Atom = 0x53306
-	Strong              Atom = 0x55906
-	Style               Atom = 0x61105
-	Sub                 Atom = 0x5a903
-	Summary             Atom = 0x61607
-	Sup                 Atom = 0x61d03
-	Svg                 Atom = 0x62003
-	System              Atom = 0x62306
-	Tabindex            Atom = 0x46308
-	Table               Atom = 0x42d05
-	Target              Atom = 0x24b06
-	Tbody               Atom = 0x2e05
-	Td                  Atom = 0x4702
-	Template            Atom = 0x62608
-	Textarea            Atom = 0x2f608
-	Tfoot               Atom = 0x8c05
-	Th                  Atom = 0x22e02
-	Thead               Atom = 0x2d405
-	Time                Atom = 0xdd04
-	Title               Atom = 0xa105
-	Tr                  Atom = 0x10502
-	Track               Atom = 0x10505
-	Translate           Atom = 0x14009
-	Tt                  Atom = 0x5302
-	Type                Atom = 0x21404
-	Typemustmatch       Atom = 0x2140d
-	U                   Atom = 0xb01
-	Ul                  Atom = 0x8a02
-	Usemap              Atom = 0x51106
-	Value               Atom = 0x4005
-	Var                 Atom = 0x11503
-	Video               Atom = 0x28105
-	Wbr                 Atom = 0x12103
-	Width               Atom = 0x50705
-	Wrap                Atom = 0x58704
-	Xmp                 Atom = 0xc103
+	A                         Atom = 0x1
+	Abbr                      Atom = 0x4
+	Accept                    Atom = 0x1a06
+	AcceptCharset             Atom = 0x1a0e
+	Accesskey                 Atom = 0x2c09
+	Acronym                   Atom = 0xaa07
+	Action                    Atom = 0x27206
+	Address                   Atom = 0x6f307
+	Align                     Atom = 0xb105
+	Allowfullscreen           Atom = 0x2080f
+	Allowpaymentrequest       Atom = 0xc113
+	Allowusermedia            Atom = 0xdd0e
+	Alt                       Atom = 0xf303
+	Annotation                Atom = 0x1c90a
+	AnnotationXml             Atom = 0x1c90e
+	Applet                    Atom = 0x31906
+	Area                      Atom = 0x35604
+	Article                   Atom = 0x3fc07
+	As                        Atom = 0x3c02
+	Aside                     Atom = 0x10705
+	Async                     Atom = 0xff05
+	Audio                     Atom = 0x11505
+	Autocomplete              Atom = 0x2780c
+	Autofocus                 Atom = 0x12109
+	Autoplay                  Atom = 0x13c08
+	B                         Atom = 0x101
+	Base                      Atom = 0x3b04
+	Basefont                  Atom = 0x3b08
+	Bdi                       Atom = 0xba03
+	Bdo                       Atom = 0x14b03
+	Bgsound                   Atom = 0x15e07
+	Big                       Atom = 0x17003
+	Blink                     Atom = 0x17305
+	Blockquote                Atom = 0x1870a
+	Body                      Atom = 0x2804
+	Br                        Atom = 0x202
+	Button                    Atom = 0x19106
+	Canvas                    Atom = 0x10306
+	Caption                   Atom = 0x23107
+	Center                    Atom = 0x22006
+	Challenge                 Atom = 0x29b09
+	Charset                   Atom = 0x2107
+	Checked                   Atom = 0x47907
+	Cite                      Atom = 0x19c04
+	Class                     Atom = 0x56405
+	Code                      Atom = 0x5c504
+	Col                       Atom = 0x1ab03
+	Colgroup                  Atom = 0x1ab08
+	Color                     Atom = 0x1bf05
+	Cols                      Atom = 0x1c404
+	Colspan                   Atom = 0x1c407
+	Command                   Atom = 0x1d707
+	Content                   Atom = 0x58b07
+	Contenteditable           Atom = 0x58b0f
+	Contextmenu               Atom = 0x3800b
+	Controls                  Atom = 0x1de08
+	Coords                    Atom = 0x1ea06
+	Crossorigin               Atom = 0x1fb0b
+	Data                      Atom = 0x4a504
+	Datalist                  Atom = 0x4a508
+	Datetime                  Atom = 0x2b808
+	Dd                        Atom = 0x2d702
+	Default                   Atom = 0x10a07
+	Defer                     Atom = 0x5c705
+	Del                       Atom = 0x45203
+	Desc                      Atom = 0x56104
+	Details                   Atom = 0x7207
+	Dfn                       Atom = 0x8703
+	Dialog                    Atom = 0xbb06
+	Dir                       Atom = 0x9303
+	Dirname                   Atom = 0x9307
+	Disabled                  Atom = 0x16408
+	Div                       Atom = 0x16b03
+	Dl                        Atom = 0x5e602
+	Download                  Atom = 0x46308
+	Draggable                 Atom = 0x17a09
+	Dropzone                  Atom = 0x40508
+	Dt                        Atom = 0x64b02
+	Em                        Atom = 0x6e02
+	Embed                     Atom = 0x6e05
+	Enctype                   Atom = 0x28d07
+	Face                      Atom = 0x21e04
+	Fieldset                  Atom = 0x22608
+	Figcaption                Atom = 0x22e0a
+	Figure                    Atom = 0x24806
+	Font                      Atom = 0x3f04
+	Footer                    Atom = 0xf606
+	For                       Atom = 0x25403
+	ForeignObject             Atom = 0x2540d
+	Foreignobject             Atom = 0x2610d
+	Form                      Atom = 0x26e04
+	Formaction                Atom = 0x26e0a
+	Formenctype               Atom = 0x2890b
+	Formmethod                Atom = 0x2a40a
+	Formnovalidate            Atom = 0x2ae0e
+	Formtarget                Atom = 0x2c00a
+	Frame                     Atom = 0x8b05
+	Frameset                  Atom = 0x8b08
+	H1                        Atom = 0x15c02
+	H2                        Atom = 0x2de02
+	H3                        Atom = 0x30d02
+	H4                        Atom = 0x34502
+	H5                        Atom = 0x34f02
+	H6                        Atom = 0x64d02
+	Head                      Atom = 0x33104
+	Header                    Atom = 0x33106
+	Headers                   Atom = 0x33107
+	Height                    Atom = 0x5206
+	Hgroup                    Atom = 0x2ca06
+	Hidden                    Atom = 0x2d506
+	High                      Atom = 0x2db04
+	Hr                        Atom = 0x15702
+	Href                      Atom = 0x2e004
+	Hreflang                  Atom = 0x2e008
+	Html                      Atom = 0x5604
+	HttpEquiv                 Atom = 0x2e80a
+	I                         Atom = 0x601
+	Icon                      Atom = 0x58a04
+	Id                        Atom = 0x10902
+	Iframe                    Atom = 0x2fc06
+	Image                     Atom = 0x30205
+	Img                       Atom = 0x30703
+	Input                     Atom = 0x44b05
+	Inputmode                 Atom = 0x44b09
+	Ins                       Atom = 0x20403
+	Integrity                 Atom = 0x23f09
+	Is                        Atom = 0x16502
+	Isindex                   Atom = 0x30f07
+	Ismap                     Atom = 0x31605
+	Itemid                    Atom = 0x38b06
+	Itemprop                  Atom = 0x19d08
+	Itemref                   Atom = 0x3cd07
+	Itemscope                 Atom = 0x67109
+	Itemtype                  Atom = 0x31f08
+	Kbd                       Atom = 0xb903
+	Keygen                    Atom = 0x3206
+	Keytype                   Atom = 0xd607
+	Kind                      Atom = 0x17704
+	Label                     Atom = 0x5905
+	Lang                      Atom = 0x2e404
+	Legend                    Atom = 0x18106
+	Li                        Atom = 0xb202
+	Link                      Atom = 0x17404
+	List                      Atom = 0x4a904
+	Listing                   Atom = 0x4a907
+	Loop                      Atom = 0x5d04
+	Low                       Atom = 0xc303
+	Main                      Atom = 0x1004
+	Malignmark                Atom = 0xb00a
+	Manifest                  Atom = 0x6d708
+	Map                       Atom = 0x31803
+	Mark                      Atom = 0xb604
+	Marquee                   Atom = 0x32707
+	Math                      Atom = 0x32e04
+	Max                       Atom = 0x33d03
+	Maxlength                 Atom = 0x33d09
+	Media                     Atom = 0xe605
+	Mediagroup                Atom = 0xe60a
+	Menu                      Atom = 0x38704
+	Menuitem                  Atom = 0x38708
+	Meta                      Atom = 0x4b804
+	Meter                     Atom = 0x9805
+	Method                    Atom = 0x2a806
+	Mglyph                    Atom = 0x30806
+	Mi                        Atom = 0x34702
+	Min                       Atom = 0x34703
+	Minlength                 Atom = 0x34709
+	Mn                        Atom = 0x2b102
+	Mo                        Atom = 0xa402
+	Ms                        Atom = 0x67402
+	Mtext                     Atom = 0x35105
+	Multiple                  Atom = 0x35f08
+	Muted                     Atom = 0x36705
+	Name                      Atom = 0x9604
+	Nav                       Atom = 0x1303
+	Nobr                      Atom = 0x3704
+	Noembed                   Atom = 0x6c07
+	Noframes                  Atom = 0x8908
+	Nomodule                  Atom = 0xa208
+	Nonce                     Atom = 0x1a605
+	Noscript                  Atom = 0x21608
+	Novalidate                Atom = 0x2b20a
+	Object                    Atom = 0x26806
+	Ol                        Atom = 0x13702
+	Onabort                   Atom = 0x19507
+	Onafterprint              Atom = 0x2360c
+	Onautocomplete            Atom = 0x2760e
+	Onautocompleteerror       Atom = 0x27613
+	Onauxclick                Atom = 0x61f0a
+	Onbeforeprint             Atom = 0x69e0d
+	Onbeforeunload            Atom = 0x6e70e
+	Onblur                    Atom = 0x56d06
+	Oncancel                  Atom = 0x11908
+	Oncanplay                 Atom = 0x14d09
+	Oncanplaythrough          Atom = 0x14d10
+	Onchange                  Atom = 0x41b08
+	Onclick                   Atom = 0x2f507
+	Onclose                   Atom = 0x36c07
+	Oncontextmenu             Atom = 0x37e0d
+	Oncopy                    Atom = 0x39106
+	Oncuechange               Atom = 0x3970b
+	Oncut                     Atom = 0x3a205
+	Ondblclick                Atom = 0x3a70a
+	Ondrag                    Atom = 0x3b106
+	Ondragend                 Atom = 0x3b109
+	Ondragenter               Atom = 0x3ba0b
+	Ondragexit                Atom = 0x3c50a
+	Ondragleave               Atom = 0x3df0b
+	Ondragover                Atom = 0x3ea0a
+	Ondragstart               Atom = 0x3f40b
+	Ondrop                    Atom = 0x40306
+	Ondurationchange          Atom = 0x41310
+	Onemptied                 Atom = 0x40a09
+	Onended                   Atom = 0x42307
+	Onerror                   Atom = 0x42a07
+	Onfocus                   Atom = 0x43107
+	Onhashchange              Atom = 0x43d0c
+	Oninput                   Atom = 0x44907
+	Oninvalid                 Atom = 0x45509
+	Onkeydown                 Atom = 0x45e09
+	Onkeypress                Atom = 0x46b0a
+	Onkeyup                   Atom = 0x48007
+	Onlanguagechange          Atom = 0x48d10
+	Onload                    Atom = 0x49d06
+	Onloadeddata              Atom = 0x49d0c
+	Onloadedmetadata          Atom = 0x4b010
+	Onloadend                 Atom = 0x4c609
+	Onloadstart               Atom = 0x4cf0b
+	Onmessage                 Atom = 0x4da09
+	Onmessageerror            Atom = 0x4da0e
+	Onmousedown               Atom = 0x4e80b
+	Onmouseenter              Atom = 0x4f30c
+	Onmouseleave              Atom = 0x4ff0c
+	Onmousemove               Atom = 0x50b0b
+	Onmouseout                Atom = 0x5160a
+	Onmouseover               Atom = 0x5230b
+	Onmouseup                 Atom = 0x52e09
+	Onmousewheel              Atom = 0x53c0c
+	Onoffline                 Atom = 0x54809
+	Ononline                  Atom = 0x55108
+	Onpagehide                Atom = 0x5590a
+	Onpageshow                Atom = 0x5730a
+	Onpaste                   Atom = 0x57f07
+	Onpause                   Atom = 0x59a07
+	Onplay                    Atom = 0x5a406
+	Onplaying                 Atom = 0x5a409
+	Onpopstate                Atom = 0x5ad0a
+	Onprogress                Atom = 0x5b70a
+	Onratechange              Atom = 0x5cc0c
+	Onrejectionhandled        Atom = 0x5d812
+	Onreset                   Atom = 0x5ea07
+	Onresize                  Atom = 0x5f108
+	Onscroll                  Atom = 0x60008
+	Onsecuritypolicyviolation Atom = 0x60819
+	Onseeked                  Atom = 0x62908
+	Onseeking                 Atom = 0x63109
+	Onselect                  Atom = 0x63a08
+	Onshow                    Atom = 0x64406
+	Onsort                    Atom = 0x64f06
+	Onstalled                 Atom = 0x65909
+	Onstorage                 Atom = 0x66209
+	Onsubmit                  Atom = 0x66b08
+	Onsuspend                 Atom = 0x67b09
+	Ontimeupdate              Atom = 0x400c
+	Ontoggle                  Atom = 0x68408
+	Onunhandledrejection      Atom = 0x68c14
+	Onunload                  Atom = 0x6ab08
+	Onvolumechange            Atom = 0x6b30e
+	Onwaiting                 Atom = 0x6c109
+	Onwheel                   Atom = 0x6ca07
+	Open                      Atom = 0x1a304
+	Optgroup                  Atom = 0x5f08
+	Optimum                   Atom = 0x6d107
+	Option                    Atom = 0x6e306
+	Output                    Atom = 0x51d06
+	P                         Atom = 0xc01
+	Param                     Atom = 0xc05
+	Pattern                   Atom = 0x6607
+	Picture                   Atom = 0x7b07
+	Ping                      Atom = 0xef04
+	Placeholder               Atom = 0x1310b
+	Plaintext                 Atom = 0x1b209
+	Playsinline               Atom = 0x1400b
+	Poster                    Atom = 0x2cf06
+	Pre                       Atom = 0x47003
+	Preload                   Atom = 0x48607
+	Progress                  Atom = 0x5b908
+	Prompt                    Atom = 0x53606
+	Public                    Atom = 0x58606
+	Q                         Atom = 0xcf01
+	Radiogroup                Atom = 0x30a
+	Rb                        Atom = 0x3a02
+	Readonly                  Atom = 0x35708
+	Referrerpolicy            Atom = 0x3d10e
+	Rel                       Atom = 0x48703
+	Required                  Atom = 0x24c08
+	Reversed                  Atom = 0x8008
+	Rows                      Atom = 0x9c04
+	Rowspan                   Atom = 0x9c07
+	Rp                        Atom = 0x23c02
+	Rt                        Atom = 0x19a02
+	Rtc                       Atom = 0x19a03
+	Ruby                      Atom = 0xfb04
+	S                         Atom = 0x2501
+	Samp                      Atom = 0x7804
+	Sandbox                   Atom = 0x12907
+	Scope                     Atom = 0x67505
+	Scoped                    Atom = 0x67506
+	Script                    Atom = 0x21806
+	Seamless                  Atom = 0x37108
+	Section                   Atom = 0x56807
+	Select                    Atom = 0x63c06
+	Selected                  Atom = 0x63c08
+	Shape                     Atom = 0x1e505
+	Size                      Atom = 0x5f504
+	Sizes                     Atom = 0x5f505
+	Slot                      Atom = 0x1ef04
+	Small                     Atom = 0x20605
+	Sortable                  Atom = 0x65108
+	Sorted                    Atom = 0x33706
+	Source                    Atom = 0x37806
+	Spacer                    Atom = 0x43706
+	Span                      Atom = 0x9f04
+	Spellcheck                Atom = 0x4740a
+	Src                       Atom = 0x5c003
+	Srcdoc                    Atom = 0x5c006
+	Srclang                   Atom = 0x5f907
+	Srcset                    Atom = 0x6f906
+	Start                     Atom = 0x3fa05
+	Step                      Atom = 0x58304
+	Strike                    Atom = 0xd206
+	Strong                    Atom = 0x6dd06
+	Style                     Atom = 0x6ff05
+	Sub                       Atom = 0x66d03
+	Summary                   Atom = 0x70407
+	Sup                       Atom = 0x70b03
+	Svg                       Atom = 0x70e03
+	System                    Atom = 0x71106
+	Tabindex                  Atom = 0x4be08
+	Table                     Atom = 0x59505
+	Target                    Atom = 0x2c406
+	Tbody                     Atom = 0x2705
+	Td                        Atom = 0x9202
+	Template                  Atom = 0x71408
+	Textarea                  Atom = 0x35208
+	Tfoot                     Atom = 0xf505
+	Th                        Atom = 0x15602
+	Thead                     Atom = 0x33005
+	Time                      Atom = 0x4204
+	Title                     Atom = 0x11005
+	Tr                        Atom = 0xcc02
+	Track                     Atom = 0x1ba05
+	Translate                 Atom = 0x1f209
+	Tt                        Atom = 0x6802
+	Type                      Atom = 0xd904
+	Typemustmatch             Atom = 0x2900d
+	U                         Atom = 0xb01
+	Ul                        Atom = 0xa702
+	Updateviacache            Atom = 0x460e
+	Usemap                    Atom = 0x59e06
+	Value                     Atom = 0x1505
+	Var                       Atom = 0x16d03
+	Video                     Atom = 0x2f105
+	Wbr                       Atom = 0x57c03
+	Width                     Atom = 0x64905
+	Workertype                Atom = 0x71c0a
+	Wrap                      Atom = 0x72604
+	Xmp                       Atom = 0x12f03
 )
 )
 
 
-const hash0 = 0xc17da63e
+const hash0 = 0x81cdf10e
 
 
-const maxAtomLen = 19
+const maxAtomLen = 25
 
 
 var table = [1 << 9]Atom{
 var table = [1 << 9]Atom{
-	0x1:   0x48a0b, // onmousemove
-	0x2:   0x5e209, // onwaiting
-	0x3:   0x1fa13, // onautocompleteerror
-	0x4:   0x5fa06, // prompt
-	0x7:   0x5eb07, // optimum
-	0x8:   0x1604,  // mark
-	0xa:   0x5ad07, // itemref
-	0xb:   0x4fe0a, // onpageshow
-	0xc:   0x57a06, // select
-	0xd:   0x17b09, // draggable
-	0xe:   0x3e03,  // nav
-	0xf:   0x17507, // command
-	0x11:  0xb01,   // u
-	0x14:  0x2d507, // headers
-	0x15:  0x44a08, // datalist
-	0x17:  0x4e04,  // samp
-	0x1a:  0x3fb09, // onkeydown
-	0x1b:  0x55f08, // onscroll
-	0x1c:  0x15003, // col
-	0x20:  0x3c908, // itemprop
-	0x21:  0x2780a, // http-equiv
-	0x22:  0x61d03, // sup
-	0x24:  0x1d008, // required
-	0x2b:  0x25e07, // preload
-	0x2c:  0x6040d, // onbeforeprint
-	0x2d:  0x3600b, // ondragenter
-	0x2e:  0x50902, // dt
-	0x2f:  0x5a708, // onsubmit
-	0x30:  0x27002, // hr
-	0x31:  0x32f0d, // oncontextmenu
-	0x33:  0x29c05, // image
-	0x34:  0x50d07, // onpause
-	0x35:  0x25906, // hgroup
-	0x36:  0x7704,  // ping
-	0x37:  0x57808, // onselect
-	0x3a:  0x11303, // div
-	0x3b:  0x1fa0e, // onautocomplete
-	0x40:  0x2eb02, // mi
-	0x41:  0x31c08, // seamless
-	0x42:  0x2807,  // charset
-	0x43:  0x8502,  // id
-	0x44:  0x5200a, // onpopstate
-	0x45:  0x3ef03, // del
-	0x46:  0x2cb07, // marquee
-	0x47:  0x3309,  // accesskey
-	0x49:  0x8d06,  // footer
-	0x4a:  0x44e04, // list
-	0x4b:  0x2b005, // ismap
-	0x51:  0x33804, // menu
-	0x52:  0x2f04,  // body
-	0x55:  0x9a08,  // frameset
-	0x56:  0x54a07, // onreset
-	0x57:  0x12705, // blink
-	0x58:  0xa105,  // title
-	0x59:  0x38807, // article
-	0x5b:  0x22e02, // th
-	0x5d:  0x13101, // q
-	0x5e:  0x3cf04, // open
-	0x5f:  0x2fa04, // area
-	0x61:  0x44206, // onload
-	0x62:  0xda04,  // font
-	0x63:  0xd604,  // base
-	0x64:  0x16207, // colspan
-	0x65:  0x53707, // keytype
-	0x66:  0x11e02, // dl
-	0x68:  0x1b008, // fieldset
-	0x6a:  0x2eb03, // min
-	0x6b:  0x11503, // var
-	0x6f:  0x2d506, // header
-	0x70:  0x13f02, // rt
-	0x71:  0x15008, // colgroup
-	0x72:  0x23502, // mn
-	0x74:  0x13a07, // onabort
-	0x75:  0x3906,  // keygen
-	0x76:  0x4c209, // onoffline
-	0x77:  0x21f09, // challenge
-	0x78:  0x2b203, // map
-	0x7a:  0x2e902, // h4
-	0x7b:  0x3b607, // onerror
-	0x7c:  0x2e109, // maxlength
-	0x7d:  0x2f505, // mtext
-	0x7e:  0xbb07,  // sandbox
-	0x7f:  0x58b06, // onsort
-	0x80:  0x100a,  // malignmark
-	0x81:  0x45d04, // meta
-	0x82:  0x7b05,  // async
-	0x83:  0x2a702, // h3
-	0x84:  0x26702, // dd
-	0x85:  0x27004, // href
-	0x86:  0x6e0a,  // mediagroup
-	0x87:  0x19406, // coords
-	0x88:  0x41107, // srclang
-	0x89:  0x34d0a, // ondblclick
-	0x8a:  0x4005,  // value
-	0x8c:  0xe908,  // oncancel
-	0x8e:  0x3230a, // spellcheck
-	0x8f:  0x9a05,  // frame
-	0x91:  0x12403, // big
-	0x94:  0x1f606, // action
-	0x95:  0x6903,  // dir
-	0x97:  0x2fb08, // readonly
-	0x99:  0x42d05, // table
-	0x9a:  0x61607, // summary
-	0x9b:  0x12103, // wbr
-	0x9c:  0x30a,   // radiogroup
-	0x9d:  0x6c04,  // name
-	0x9f:  0x62306, // system
-	0xa1:  0x15d05, // color
-	0xa2:  0x7f06,  // canvas
-	0xa3:  0x25504, // html
-	0xa5:  0x56f09, // onseeking
-	0xac:  0x4f905, // shape
-	0xad:  0x25f03, // rel
-	0xae:  0x28510, // oncanplaythrough
-	0xaf:  0x3760a, // ondragover
-	0xb0:  0x62608, // template
-	0xb1:  0x1d80d, // foreignObject
-	0xb3:  0x9204,  // rows
-	0xb6:  0x44e07, // listing
-	0xb7:  0x49c06, // output
-	0xb9:  0x3310b, // contextmenu
-	0xbb:  0x11f03, // low
-	0xbc:  0x1c602, // rp
-	0xbd:  0x5bb09, // onsuspend
-	0xbe:  0x13606, // button
-	0xbf:  0x4db04, // desc
-	0xc1:  0x4e207, // section
-	0xc2:  0x52a0a, // onprogress
-	0xc3:  0x59e09, // onstorage
-	0xc4:  0x2d204, // math
-	0xc5:  0x4503,  // alt
-	0xc7:  0x8a02,  // ul
-	0xc8:  0x5107,  // pattern
-	0xc9:  0x4b60c, // onmousewheel
-	0xca:  0x35709, // ondragend
-	0xcb:  0xaf04,  // ruby
-	0xcc:  0xc01,   // p
-	0xcd:  0x31707, // onclose
-	0xce:  0x24205, // meter
-	0xcf:  0x11807, // bgsound
-	0xd2:  0x25106, // height
-	0xd4:  0x101,   // b
-	0xd5:  0x2c308, // itemtype
-	0xd8:  0x1bb07, // caption
-	0xd9:  0x10c08, // disabled
-	0xdb:  0x33808, // menuitem
-	0xdc:  0x62003, // svg
-	0xdd:  0x18f05, // small
-	0xde:  0x44a04, // data
-	0xe0:  0x4cb08, // ononline
-	0xe1:  0x2a206, // mglyph
-	0xe3:  0x6505,  // embed
-	0xe4:  0x10502, // tr
-	0xe5:  0x46b0b, // onloadstart
-	0xe7:  0x3c306, // srcdoc
-	0xeb:  0x5c408, // ontoggle
-	0xed:  0xe703,  // bdo
-	0xee:  0x4702,  // td
-	0xef:  0x8305,  // aside
-	0xf0:  0x29402, // h2
-	0xf1:  0x52c08, // progress
-	0xf2:  0x12c0a, // blockquote
-	0xf4:  0xf005,  // label
-	0xf5:  0x601,   // i
-	0xf7:  0x9207,  // rowspan
-	0xfb:  0x51709, // onplaying
-	0xfd:  0x2a103, // img
-	0xfe:  0xf608,  // optgroup
-	0xff:  0x42307, // content
-	0x101: 0x53e0c, // onratechange
-	0x103: 0x3da0c, // onhashchange
-	0x104: 0x4807,  // details
-	0x106: 0x40008, // download
-	0x109: 0x14009, // translate
-	0x10b: 0x4230f, // contenteditable
-	0x10d: 0x36b0b, // ondragleave
-	0x10e: 0x2106,  // accept
-	0x10f: 0x57a08, // selected
-	0x112: 0x1f20a, // formaction
-	0x113: 0x5b506, // center
-	0x115: 0x45510, // onloadedmetadata
-	0x116: 0x12804, // link
-	0x117: 0xdd04,  // time
-	0x118: 0x19f0b, // crossorigin
-	0x119: 0x3bd07, // onfocus
-	0x11a: 0x58704, // wrap
-	0x11b: 0x42204, // icon
-	0x11d: 0x28105, // video
-	0x11e: 0x4de05, // class
-	0x121: 0x5d40e, // onvolumechange
-	0x122: 0xaa06,  // onblur
-	0x123: 0x2b909, // itemscope
-	0x124: 0x61105, // style
-	0x127: 0x41e06, // public
-	0x129: 0x2320e, // formnovalidate
-	0x12a: 0x58206, // onshow
-	0x12c: 0x51706, // onplay
-	0x12d: 0x3c804, // cite
-	0x12e: 0x2bc02, // ms
-	0x12f: 0xdb0c,  // ontimeupdate
-	0x130: 0x10904, // kind
-	0x131: 0x2470a, // formtarget
-	0x135: 0x3af07, // onended
-	0x136: 0x26506, // hidden
-	0x137: 0x2c01,  // s
-	0x139: 0x2280a, // formmethod
-	0x13a: 0x3e805, // input
-	0x13c: 0x50b02, // h6
-	0x13d: 0xc902,  // ol
-	0x13e: 0x3420b, // oncuechange
-	0x13f: 0x1e50d, // foreignobject
-	0x143: 0x4e70e, // onbeforeunload
-	0x144: 0x2bd05, // scope
-	0x145: 0x39609, // onemptied
-	0x146: 0x14b05, // defer
-	0x147: 0xc103,  // xmp
-	0x148: 0x39f10, // ondurationchange
-	0x149: 0x1903,  // kbd
-	0x14c: 0x47609, // onmessage
-	0x14d: 0x60006, // option
-	0x14e: 0x2eb09, // minlength
-	0x14f: 0x32807, // checked
-	0x150: 0xce08,  // autoplay
-	0x152: 0x202,   // br
-	0x153: 0x2360a, // novalidate
-	0x156: 0x6307,  // noembed
-	0x159: 0x31007, // onclick
-	0x15a: 0x47f0b, // onmousedown
-	0x15b: 0x3a708, // onchange
-	0x15e: 0x3f209, // oninvalid
-	0x15f: 0x2bd06, // scoped
-	0x160: 0x18808, // controls
-	0x161: 0x30b05, // muted
-	0x162: 0x58d08, // sortable
-	0x163: 0x51106, // usemap
-	0x164: 0x1b80a, // figcaption
-	0x165: 0x35706, // ondrag
-	0x166: 0x26b04, // high
-	0x168: 0x3c303, // src
-	0x169: 0x15706, // poster
-	0x16b: 0x1670e, // annotation-xml
-	0x16c: 0x5f704, // step
-	0x16d: 0x4,     // abbr
-	0x16e: 0x1b06,  // dialog
-	0x170: 0x1202,  // li
-	0x172: 0x3ed02, // mo
-	0x175: 0x1d803, // for
-	0x176: 0x1a803, // ins
-	0x178: 0x55504, // size
-	0x179: 0x43210, // onlanguagechange
-	0x17a: 0x8607,  // default
-	0x17b: 0x1a03,  // bdi
-	0x17c: 0x4d30a, // onpagehide
-	0x17d: 0x6907,  // dirname
-	0x17e: 0x21404, // type
-	0x17f: 0x1f204, // form
-	0x181: 0x28509, // oncanplay
-	0x182: 0x6103,  // dfn
-	0x183: 0x46308, // tabindex
-	0x186: 0x6502,  // em
-	0x187: 0x27404, // lang
-	0x189: 0x39108, // dropzone
-	0x18a: 0x4080a, // onkeypress
-	0x18b: 0x23c08, // datetime
-	0x18c: 0x16204, // cols
-	0x18d: 0x1,     // a
-	0x18e: 0x4420c, // onloadeddata
-	0x190: 0xa605,  // audio
-	0x192: 0x2e05,  // tbody
-	0x193: 0x22c06, // method
-	0x195: 0xf404,  // loop
-	0x196: 0x29606, // iframe
-	0x198: 0x2d504, // head
-	0x19e: 0x5f108, // manifest
-	0x19f: 0xb309,  // autofocus
-	0x1a0: 0x14904, // code
-	0x1a1: 0x55906, // strong
-	0x1a2: 0x30308, // multiple
-	0x1a3: 0xc05,   // param
-	0x1a6: 0x21107, // enctype
-	0x1a7: 0x5b304, // face
-	0x1a8: 0xfd09,  // plaintext
-	0x1a9: 0x26e02, // h1
-	0x1aa: 0x59509, // onstalled
-	0x1ad: 0x3d406, // script
-	0x1ae: 0x2db06, // spacer
-	0x1af: 0x55108, // onresize
-	0x1b0: 0x4a20b, // onmouseover
-	0x1b1: 0x5cc08, // onunload
-	0x1b2: 0x56708, // onseeked
-	0x1b4: 0x2140d, // typemustmatch
-	0x1b5: 0x1cc06, // figure
-	0x1b6: 0x4950a, // onmouseout
-	0x1b7: 0x25e03, // pre
-	0x1b8: 0x50705, // width
-	0x1b9: 0x19906, // sorted
-	0x1bb: 0x5704,  // nobr
-	0x1be: 0x5302,  // tt
-	0x1bf: 0x1105,  // align
-	0x1c0: 0x3e607, // oninput
-	0x1c3: 0x41807, // onkeyup
-	0x1c6: 0x1c00c, // onafterprint
-	0x1c7: 0x210e,  // accept-charset
-	0x1c8: 0x33c06, // itemid
-	0x1c9: 0x3e809, // inputmode
-	0x1cb: 0x53306, // strike
-	0x1cc: 0x5a903, // sub
-	0x1cd: 0x10505, // track
-	0x1ce: 0x38605, // start
-	0x1d0: 0xd608,  // basefont
-	0x1d6: 0x1aa06, // source
-	0x1d7: 0x18206, // legend
-	0x1d8: 0x2d405, // thead
-	0x1da: 0x8c05,  // tfoot
-	0x1dd: 0x1ec06, // object
-	0x1de: 0x6e05,  // media
-	0x1df: 0x1670a, // annotation
-	0x1e0: 0x20d0b, // formenctype
-	0x1e2: 0x3d208, // noscript
-	0x1e4: 0x55505, // sizes
-	0x1e5: 0x1fc0c, // autocomplete
-	0x1e6: 0x9504,  // span
-	0x1e7: 0x9808,  // noframes
-	0x1e8: 0x24b06, // target
-	0x1e9: 0x38f06, // ondrop
-	0x1ea: 0x2b306, // applet
-	0x1ec: 0x5a08,  // reversed
-	0x1f0: 0x2a907, // isindex
-	0x1f3: 0x27008, // hreflang
-	0x1f5: 0x2f302, // h5
-	0x1f6: 0x4f307, // address
-	0x1fa: 0x2e103, // max
-	0x1fb: 0xc30b,  // placeholder
-	0x1fc: 0x2f608, // textarea
-	0x1fe: 0x4ad09, // onmouseup
-	0x1ff: 0x3800b, // ondragstart
+	0x1:   0xe60a,  // mediagroup
+	0x2:   0x2e404, // lang
+	0x4:   0x2c09,  // accesskey
+	0x5:   0x8b08,  // frameset
+	0x7:   0x63a08, // onselect
+	0x8:   0x71106, // system
+	0xa:   0x64905, // width
+	0xc:   0x2890b, // formenctype
+	0xd:   0x13702, // ol
+	0xe:   0x3970b, // oncuechange
+	0x10:  0x14b03, // bdo
+	0x11:  0x11505, // audio
+	0x12:  0x17a09, // draggable
+	0x14:  0x2f105, // video
+	0x15:  0x2b102, // mn
+	0x16:  0x38704, // menu
+	0x17:  0x2cf06, // poster
+	0x19:  0xf606,  // footer
+	0x1a:  0x2a806, // method
+	0x1b:  0x2b808, // datetime
+	0x1c:  0x19507, // onabort
+	0x1d:  0x460e,  // updateviacache
+	0x1e:  0xff05,  // async
+	0x1f:  0x49d06, // onload
+	0x21:  0x11908, // oncancel
+	0x22:  0x62908, // onseeked
+	0x23:  0x30205, // image
+	0x24:  0x5d812, // onrejectionhandled
+	0x26:  0x17404, // link
+	0x27:  0x51d06, // output
+	0x28:  0x33104, // head
+	0x29:  0x4ff0c, // onmouseleave
+	0x2a:  0x57f07, // onpaste
+	0x2b:  0x5a409, // onplaying
+	0x2c:  0x1c407, // colspan
+	0x2f:  0x1bf05, // color
+	0x30:  0x5f504, // size
+	0x31:  0x2e80a, // http-equiv
+	0x33:  0x601,   // i
+	0x34:  0x5590a, // onpagehide
+	0x35:  0x68c14, // onunhandledrejection
+	0x37:  0x42a07, // onerror
+	0x3a:  0x3b08,  // basefont
+	0x3f:  0x1303,  // nav
+	0x40:  0x17704, // kind
+	0x41:  0x35708, // readonly
+	0x42:  0x30806, // mglyph
+	0x44:  0xb202,  // li
+	0x46:  0x2d506, // hidden
+	0x47:  0x70e03, // svg
+	0x48:  0x58304, // step
+	0x49:  0x23f09, // integrity
+	0x4a:  0x58606, // public
+	0x4c:  0x1ab03, // col
+	0x4d:  0x1870a, // blockquote
+	0x4e:  0x34f02, // h5
+	0x50:  0x5b908, // progress
+	0x51:  0x5f505, // sizes
+	0x52:  0x34502, // h4
+	0x56:  0x33005, // thead
+	0x57:  0xd607,  // keytype
+	0x58:  0x5b70a, // onprogress
+	0x59:  0x44b09, // inputmode
+	0x5a:  0x3b109, // ondragend
+	0x5d:  0x3a205, // oncut
+	0x5e:  0x43706, // spacer
+	0x5f:  0x1ab08, // colgroup
+	0x62:  0x16502, // is
+	0x65:  0x3c02,  // as
+	0x66:  0x54809, // onoffline
+	0x67:  0x33706, // sorted
+	0x69:  0x48d10, // onlanguagechange
+	0x6c:  0x43d0c, // onhashchange
+	0x6d:  0x9604,  // name
+	0x6e:  0xf505,  // tfoot
+	0x6f:  0x56104, // desc
+	0x70:  0x33d03, // max
+	0x72:  0x1ea06, // coords
+	0x73:  0x30d02, // h3
+	0x74:  0x6e70e, // onbeforeunload
+	0x75:  0x9c04,  // rows
+	0x76:  0x63c06, // select
+	0x77:  0x9805,  // meter
+	0x78:  0x38b06, // itemid
+	0x79:  0x53c0c, // onmousewheel
+	0x7a:  0x5c006, // srcdoc
+	0x7d:  0x1ba05, // track
+	0x7f:  0x31f08, // itemtype
+	0x82:  0xa402,  // mo
+	0x83:  0x41b08, // onchange
+	0x84:  0x33107, // headers
+	0x85:  0x5cc0c, // onratechange
+	0x86:  0x60819, // onsecuritypolicyviolation
+	0x88:  0x4a508, // datalist
+	0x89:  0x4e80b, // onmousedown
+	0x8a:  0x1ef04, // slot
+	0x8b:  0x4b010, // onloadedmetadata
+	0x8c:  0x1a06,  // accept
+	0x8d:  0x26806, // object
+	0x91:  0x6b30e, // onvolumechange
+	0x92:  0x2107,  // charset
+	0x93:  0x27613, // onautocompleteerror
+	0x94:  0xc113,  // allowpaymentrequest
+	0x95:  0x2804,  // body
+	0x96:  0x10a07, // default
+	0x97:  0x63c08, // selected
+	0x98:  0x21e04, // face
+	0x99:  0x1e505, // shape
+	0x9b:  0x68408, // ontoggle
+	0x9e:  0x64b02, // dt
+	0x9f:  0xb604,  // mark
+	0xa1:  0xb01,   // u
+	0xa4:  0x6ab08, // onunload
+	0xa5:  0x5d04,  // loop
+	0xa6:  0x16408, // disabled
+	0xaa:  0x42307, // onended
+	0xab:  0xb00a,  // malignmark
+	0xad:  0x67b09, // onsuspend
+	0xae:  0x35105, // mtext
+	0xaf:  0x64f06, // onsort
+	0xb0:  0x19d08, // itemprop
+	0xb3:  0x67109, // itemscope
+	0xb4:  0x17305, // blink
+	0xb6:  0x3b106, // ondrag
+	0xb7:  0xa702,  // ul
+	0xb8:  0x26e04, // form
+	0xb9:  0x12907, // sandbox
+	0xba:  0x8b05,  // frame
+	0xbb:  0x1505,  // value
+	0xbc:  0x66209, // onstorage
+	0xbf:  0xaa07,  // acronym
+	0xc0:  0x19a02, // rt
+	0xc2:  0x202,   // br
+	0xc3:  0x22608, // fieldset
+	0xc4:  0x2900d, // typemustmatch
+	0xc5:  0xa208,  // nomodule
+	0xc6:  0x6c07,  // noembed
+	0xc7:  0x69e0d, // onbeforeprint
+	0xc8:  0x19106, // button
+	0xc9:  0x2f507, // onclick
+	0xca:  0x70407, // summary
+	0xcd:  0xfb04,  // ruby
+	0xce:  0x56405, // class
+	0xcf:  0x3f40b, // ondragstart
+	0xd0:  0x23107, // caption
+	0xd4:  0xdd0e,  // allowusermedia
+	0xd5:  0x4cf0b, // onloadstart
+	0xd9:  0x16b03, // div
+	0xda:  0x4a904, // list
+	0xdb:  0x32e04, // math
+	0xdc:  0x44b05, // input
+	0xdf:  0x3ea0a, // ondragover
+	0xe0:  0x2de02, // h2
+	0xe2:  0x1b209, // plaintext
+	0xe4:  0x4f30c, // onmouseenter
+	0xe7:  0x47907, // checked
+	0xe8:  0x47003, // pre
+	0xea:  0x35f08, // multiple
+	0xeb:  0xba03,  // bdi
+	0xec:  0x33d09, // maxlength
+	0xed:  0xcf01,  // q
+	0xee:  0x61f0a, // onauxclick
+	0xf0:  0x57c03, // wbr
+	0xf2:  0x3b04,  // base
+	0xf3:  0x6e306, // option
+	0xf5:  0x41310, // ondurationchange
+	0xf7:  0x8908,  // noframes
+	0xf9:  0x40508, // dropzone
+	0xfb:  0x67505, // scope
+	0xfc:  0x8008,  // reversed
+	0xfd:  0x3ba0b, // ondragenter
+	0xfe:  0x3fa05, // start
+	0xff:  0x12f03, // xmp
+	0x100: 0x5f907, // srclang
+	0x101: 0x30703, // img
+	0x104: 0x101,   // b
+	0x105: 0x25403, // for
+	0x106: 0x10705, // aside
+	0x107: 0x44907, // oninput
+	0x108: 0x35604, // area
+	0x109: 0x2a40a, // formmethod
+	0x10a: 0x72604, // wrap
+	0x10c: 0x23c02, // rp
+	0x10d: 0x46b0a, // onkeypress
+	0x10e: 0x6802,  // tt
+	0x110: 0x34702, // mi
+	0x111: 0x36705, // muted
+	0x112: 0xf303,  // alt
+	0x113: 0x5c504, // code
+	0x114: 0x6e02,  // em
+	0x115: 0x3c50a, // ondragexit
+	0x117: 0x9f04,  // span
+	0x119: 0x6d708, // manifest
+	0x11a: 0x38708, // menuitem
+	0x11b: 0x58b07, // content
+	0x11d: 0x6c109, // onwaiting
+	0x11f: 0x4c609, // onloadend
+	0x121: 0x37e0d, // oncontextmenu
+	0x123: 0x56d06, // onblur
+	0x124: 0x3fc07, // article
+	0x125: 0x9303,  // dir
+	0x126: 0xef04,  // ping
+	0x127: 0x24c08, // required
+	0x128: 0x45509, // oninvalid
+	0x129: 0xb105,  // align
+	0x12b: 0x58a04, // icon
+	0x12c: 0x64d02, // h6
+	0x12d: 0x1c404, // cols
+	0x12e: 0x22e0a, // figcaption
+	0x12f: 0x45e09, // onkeydown
+	0x130: 0x66b08, // onsubmit
+	0x131: 0x14d09, // oncanplay
+	0x132: 0x70b03, // sup
+	0x133: 0xc01,   // p
+	0x135: 0x40a09, // onemptied
+	0x136: 0x39106, // oncopy
+	0x137: 0x19c04, // cite
+	0x138: 0x3a70a, // ondblclick
+	0x13a: 0x50b0b, // onmousemove
+	0x13c: 0x66d03, // sub
+	0x13d: 0x48703, // rel
+	0x13e: 0x5f08,  // optgroup
+	0x142: 0x9c07,  // rowspan
+	0x143: 0x37806, // source
+	0x144: 0x21608, // noscript
+	0x145: 0x1a304, // open
+	0x146: 0x20403, // ins
+	0x147: 0x2540d, // foreignObject
+	0x148: 0x5ad0a, // onpopstate
+	0x14a: 0x28d07, // enctype
+	0x14b: 0x2760e, // onautocomplete
+	0x14c: 0x35208, // textarea
+	0x14e: 0x2780c, // autocomplete
+	0x14f: 0x15702, // hr
+	0x150: 0x1de08, // controls
+	0x151: 0x10902, // id
+	0x153: 0x2360c, // onafterprint
+	0x155: 0x2610d, // foreignobject
+	0x156: 0x32707, // marquee
+	0x157: 0x59a07, // onpause
+	0x158: 0x5e602, // dl
+	0x159: 0x5206,  // height
+	0x15a: 0x34703, // min
+	0x15b: 0x9307,  // dirname
+	0x15c: 0x1f209, // translate
+	0x15d: 0x5604,  // html
+	0x15e: 0x34709, // minlength
+	0x15f: 0x48607, // preload
+	0x160: 0x71408, // template
+	0x161: 0x3df0b, // ondragleave
+	0x162: 0x3a02,  // rb
+	0x164: 0x5c003, // src
+	0x165: 0x6dd06, // strong
+	0x167: 0x7804,  // samp
+	0x168: 0x6f307, // address
+	0x169: 0x55108, // ononline
+	0x16b: 0x1310b, // placeholder
+	0x16c: 0x2c406, // target
+	0x16d: 0x20605, // small
+	0x16e: 0x6ca07, // onwheel
+	0x16f: 0x1c90a, // annotation
+	0x170: 0x4740a, // spellcheck
+	0x171: 0x7207,  // details
+	0x172: 0x10306, // canvas
+	0x173: 0x12109, // autofocus
+	0x174: 0xc05,   // param
+	0x176: 0x46308, // download
+	0x177: 0x45203, // del
+	0x178: 0x36c07, // onclose
+	0x179: 0xb903,  // kbd
+	0x17a: 0x31906, // applet
+	0x17b: 0x2e004, // href
+	0x17c: 0x5f108, // onresize
+	0x17e: 0x49d0c, // onloadeddata
+	0x180: 0xcc02,  // tr
+	0x181: 0x2c00a, // formtarget
+	0x182: 0x11005, // title
+	0x183: 0x6ff05, // style
+	0x184: 0xd206,  // strike
+	0x185: 0x59e06, // usemap
+	0x186: 0x2fc06, // iframe
+	0x187: 0x1004,  // main
+	0x189: 0x7b07,  // picture
+	0x18c: 0x31605, // ismap
+	0x18e: 0x4a504, // data
+	0x18f: 0x5905,  // label
+	0x191: 0x3d10e, // referrerpolicy
+	0x192: 0x15602, // th
+	0x194: 0x53606, // prompt
+	0x195: 0x56807, // section
+	0x197: 0x6d107, // optimum
+	0x198: 0x2db04, // high
+	0x199: 0x15c02, // h1
+	0x19a: 0x65909, // onstalled
+	0x19b: 0x16d03, // var
+	0x19c: 0x4204,  // time
+	0x19e: 0x67402, // ms
+	0x19f: 0x33106, // header
+	0x1a0: 0x4da09, // onmessage
+	0x1a1: 0x1a605, // nonce
+	0x1a2: 0x26e0a, // formaction
+	0x1a3: 0x22006, // center
+	0x1a4: 0x3704,  // nobr
+	0x1a5: 0x59505, // table
+	0x1a6: 0x4a907, // listing
+	0x1a7: 0x18106, // legend
+	0x1a9: 0x29b09, // challenge
+	0x1aa: 0x24806, // figure
+	0x1ab: 0xe605,  // media
+	0x1ae: 0xd904,  // type
+	0x1af: 0x3f04,  // font
+	0x1b0: 0x4da0e, // onmessageerror
+	0x1b1: 0x37108, // seamless
+	0x1b2: 0x8703,  // dfn
+	0x1b3: 0x5c705, // defer
+	0x1b4: 0xc303,  // low
+	0x1b5: 0x19a03, // rtc
+	0x1b6: 0x5230b, // onmouseover
+	0x1b7: 0x2b20a, // novalidate
+	0x1b8: 0x71c0a, // workertype
+	0x1ba: 0x3cd07, // itemref
+	0x1bd: 0x1,     // a
+	0x1be: 0x31803, // map
+	0x1bf: 0x400c,  // ontimeupdate
+	0x1c0: 0x15e07, // bgsound
+	0x1c1: 0x3206,  // keygen
+	0x1c2: 0x2705,  // tbody
+	0x1c5: 0x64406, // onshow
+	0x1c7: 0x2501,  // s
+	0x1c8: 0x6607,  // pattern
+	0x1cc: 0x14d10, // oncanplaythrough
+	0x1ce: 0x2d702, // dd
+	0x1cf: 0x6f906, // srcset
+	0x1d0: 0x17003, // big
+	0x1d2: 0x65108, // sortable
+	0x1d3: 0x48007, // onkeyup
+	0x1d5: 0x5a406, // onplay
+	0x1d7: 0x4b804, // meta
+	0x1d8: 0x40306, // ondrop
+	0x1da: 0x60008, // onscroll
+	0x1db: 0x1fb0b, // crossorigin
+	0x1dc: 0x5730a, // onpageshow
+	0x1dd: 0x4,     // abbr
+	0x1de: 0x9202,  // td
+	0x1df: 0x58b0f, // contenteditable
+	0x1e0: 0x27206, // action
+	0x1e1: 0x1400b, // playsinline
+	0x1e2: 0x43107, // onfocus
+	0x1e3: 0x2e008, // hreflang
+	0x1e5: 0x5160a, // onmouseout
+	0x1e6: 0x5ea07, // onreset
+	0x1e7: 0x13c08, // autoplay
+	0x1e8: 0x63109, // onseeking
+	0x1ea: 0x67506, // scoped
+	0x1ec: 0x30a,   // radiogroup
+	0x1ee: 0x3800b, // contextmenu
+	0x1ef: 0x52e09, // onmouseup
+	0x1f1: 0x2ca06, // hgroup
+	0x1f2: 0x2080f, // allowfullscreen
+	0x1f3: 0x4be08, // tabindex
+	0x1f6: 0x30f07, // isindex
+	0x1f7: 0x1a0e,  // accept-charset
+	0x1f8: 0x2ae0e, // formnovalidate
+	0x1fb: 0x1c90e, // annotation-xml
+	0x1fc: 0x6e05,  // embed
+	0x1fd: 0x21806, // script
+	0x1fe: 0xbb06,  // dialog
+	0x1ff: 0x1d707, // command
 }
 }
 
 
-const atomText = "abbradiogrouparamalignmarkbdialogaccept-charsetbodyaccesskey" +
-	"genavaluealtdetailsampatternobreversedfnoembedirnamediagroup" +
-	"ingasyncanvasidefaultfooterowspanoframesetitleaudionblurubya" +
-	"utofocusandboxmplaceholderautoplaybasefontimeupdatebdoncance" +
-	"labelooptgrouplaintextrackindisabledivarbgsoundlowbrbigblink" +
-	"blockquotebuttonabortranslatecodefercolgroupostercolorcolspa" +
-	"nnotation-xmlcommandraggablegendcontrolsmallcoordsortedcross" +
-	"originsourcefieldsetfigcaptionafterprintfigurequiredforeignO" +
-	"bjectforeignobjectformactionautocompleteerrorformenctypemust" +
-	"matchallengeformmethodformnovalidatetimeterformtargetheightm" +
-	"lhgroupreloadhiddenhigh1hreflanghttp-equivideoncanplaythroug" +
-	"h2iframeimageimglyph3isindexismappletitemscopeditemtypemarqu" +
-	"eematheaderspacermaxlength4minlength5mtextareadonlymultiplem" +
-	"utedonclickoncloseamlesspellcheckedoncontextmenuitemidoncuec" +
-	"hangeondblclickondragendondragenterondragleaveondragoverondr" +
-	"agstarticleondropzonemptiedondurationchangeonendedonerroronf" +
-	"ocusrcdocitempropenoscriptonhashchangeoninputmodeloninvalido" +
-	"nkeydownloadonkeypressrclangonkeyupublicontenteditableonlang" +
-	"uagechangeonloadeddatalistingonloadedmetadatabindexonloadsta" +
-	"rtonmessageonmousedownonmousemoveonmouseoutputonmouseoveronm" +
-	"ouseuponmousewheelonofflineononlineonpagehidesclassectionbef" +
-	"oreunloaddresshapeonpageshowidth6onpausemaponplayingonpopsta" +
-	"teonprogresstrikeytypeonratechangeonresetonresizestrongonscr" +
-	"ollonseekedonseekingonselectedonshowraponsortableonstalledon" +
-	"storageonsubmitemrefacenteronsuspendontoggleonunloadonvolume" +
-	"changeonwaitingoptimumanifestepromptoptionbeforeprintstylesu" +
-	"mmarysupsvgsystemplate"
+const atomText = "abbradiogrouparamainavalueaccept-charsetbodyaccesskeygenobrb" +
+	"asefontimeupdateviacacheightmlabelooptgroupatternoembedetail" +
+	"sampictureversedfnoframesetdirnameterowspanomoduleacronymali" +
+	"gnmarkbdialogallowpaymentrequestrikeytypeallowusermediagroup" +
+	"ingaltfooterubyasyncanvasidefaultitleaudioncancelautofocusan" +
+	"dboxmplaceholderautoplaysinlinebdoncanplaythrough1bgsoundisa" +
+	"bledivarbigblinkindraggablegendblockquotebuttonabortcitempro" +
+	"penoncecolgrouplaintextrackcolorcolspannotation-xmlcommandco" +
+	"ntrolshapecoordslotranslatecrossoriginsmallowfullscreenoscri" +
+	"ptfacenterfieldsetfigcaptionafterprintegrityfigurequiredfore" +
+	"ignObjectforeignobjectformactionautocompleteerrorformenctype" +
+	"mustmatchallengeformmethodformnovalidatetimeformtargethgroup" +
+	"osterhiddenhigh2hreflanghttp-equivideonclickiframeimageimgly" +
+	"ph3isindexismappletitemtypemarqueematheadersortedmaxlength4m" +
+	"inlength5mtextareadonlymultiplemutedoncloseamlessourceoncont" +
+	"extmenuitemidoncopyoncuechangeoncutondblclickondragendondrag" +
+	"enterondragexitemreferrerpolicyondragleaveondragoverondragst" +
+	"articleondropzonemptiedondurationchangeonendedonerroronfocus" +
+	"paceronhashchangeoninputmodeloninvalidonkeydownloadonkeypres" +
+	"spellcheckedonkeyupreloadonlanguagechangeonloadeddatalisting" +
+	"onloadedmetadatabindexonloadendonloadstartonmessageerroronmo" +
+	"usedownonmouseenteronmouseleaveonmousemoveonmouseoutputonmou" +
+	"seoveronmouseupromptonmousewheelonofflineononlineonpagehides" +
+	"classectionbluronpageshowbronpastepublicontenteditableonpaus" +
+	"emaponplayingonpopstateonprogressrcdocodeferonratechangeonre" +
+	"jectionhandledonresetonresizesrclangonscrollonsecuritypolicy" +
+	"violationauxclickonseekedonseekingonselectedonshowidth6onsor" +
+	"tableonstalledonstorageonsubmitemscopedonsuspendontoggleonun" +
+	"handledrejectionbeforeprintonunloadonvolumechangeonwaitingon" +
+	"wheeloptimumanifestrongoptionbeforeunloaddressrcsetstylesumm" +
+	"arysupsvgsystemplateworkertypewrap"

+ 35 - 10
vendor/golang.org/x/net/html/atom/table_test.go

@@ -1,23 +1,29 @@
-// generated by go run gen.go -test; DO NOT EDIT
+// Code generated by go generate gen.go; DO NOT EDIT.
+
+//go:generate go run gen.go -test
 
 
 package atom
 package atom
 
 
 var testAtomList = []string{
 var testAtomList = []string{
 	"a",
 	"a",
 	"abbr",
 	"abbr",
-	"abbr",
 	"accept",
 	"accept",
 	"accept-charset",
 	"accept-charset",
 	"accesskey",
 	"accesskey",
+	"acronym",
 	"action",
 	"action",
 	"address",
 	"address",
 	"align",
 	"align",
+	"allowfullscreen",
+	"allowpaymentrequest",
+	"allowusermedia",
 	"alt",
 	"alt",
 	"annotation",
 	"annotation",
 	"annotation-xml",
 	"annotation-xml",
 	"applet",
 	"applet",
 	"area",
 	"area",
 	"article",
 	"article",
+	"as",
 	"aside",
 	"aside",
 	"async",
 	"async",
 	"audio",
 	"audio",
@@ -43,7 +49,6 @@ var testAtomList = []string{
 	"charset",
 	"charset",
 	"checked",
 	"checked",
 	"cite",
 	"cite",
-	"cite",
 	"class",
 	"class",
 	"code",
 	"code",
 	"col",
 	"col",
@@ -52,7 +57,6 @@ var testAtomList = []string{
 	"cols",
 	"cols",
 	"colspan",
 	"colspan",
 	"command",
 	"command",
-	"command",
 	"content",
 	"content",
 	"contenteditable",
 	"contenteditable",
 	"contextmenu",
 	"contextmenu",
@@ -60,7 +64,6 @@ var testAtomList = []string{
 	"coords",
 	"coords",
 	"crossorigin",
 	"crossorigin",
 	"data",
 	"data",
-	"data",
 	"datalist",
 	"datalist",
 	"datetime",
 	"datetime",
 	"dd",
 	"dd",
@@ -93,7 +96,6 @@ var testAtomList = []string{
 	"foreignObject",
 	"foreignObject",
 	"foreignobject",
 	"foreignobject",
 	"form",
 	"form",
-	"form",
 	"formaction",
 	"formaction",
 	"formenctype",
 	"formenctype",
 	"formmethod",
 	"formmethod",
@@ -128,6 +130,8 @@ var testAtomList = []string{
 	"input",
 	"input",
 	"inputmode",
 	"inputmode",
 	"ins",
 	"ins",
+	"integrity",
+	"is",
 	"isindex",
 	"isindex",
 	"ismap",
 	"ismap",
 	"itemid",
 	"itemid",
@@ -140,7 +144,6 @@ var testAtomList = []string{
 	"keytype",
 	"keytype",
 	"kind",
 	"kind",
 	"label",
 	"label",
-	"label",
 	"lang",
 	"lang",
 	"legend",
 	"legend",
 	"li",
 	"li",
@@ -149,6 +152,7 @@ var testAtomList = []string{
 	"listing",
 	"listing",
 	"loop",
 	"loop",
 	"low",
 	"low",
+	"main",
 	"malignmark",
 	"malignmark",
 	"manifest",
 	"manifest",
 	"map",
 	"map",
@@ -179,6 +183,8 @@ var testAtomList = []string{
 	"nobr",
 	"nobr",
 	"noembed",
 	"noembed",
 	"noframes",
 	"noframes",
+	"nomodule",
+	"nonce",
 	"noscript",
 	"noscript",
 	"novalidate",
 	"novalidate",
 	"object",
 	"object",
@@ -187,6 +193,7 @@ var testAtomList = []string{
 	"onafterprint",
 	"onafterprint",
 	"onautocomplete",
 	"onautocomplete",
 	"onautocompleteerror",
 	"onautocompleteerror",
+	"onauxclick",
 	"onbeforeprint",
 	"onbeforeprint",
 	"onbeforeunload",
 	"onbeforeunload",
 	"onblur",
 	"onblur",
@@ -197,11 +204,14 @@ var testAtomList = []string{
 	"onclick",
 	"onclick",
 	"onclose",
 	"onclose",
 	"oncontextmenu",
 	"oncontextmenu",
+	"oncopy",
 	"oncuechange",
 	"oncuechange",
+	"oncut",
 	"ondblclick",
 	"ondblclick",
 	"ondrag",
 	"ondrag",
 	"ondragend",
 	"ondragend",
 	"ondragenter",
 	"ondragenter",
+	"ondragexit",
 	"ondragleave",
 	"ondragleave",
 	"ondragover",
 	"ondragover",
 	"ondragstart",
 	"ondragstart",
@@ -221,9 +231,13 @@ var testAtomList = []string{
 	"onload",
 	"onload",
 	"onloadeddata",
 	"onloadeddata",
 	"onloadedmetadata",
 	"onloadedmetadata",
+	"onloadend",
 	"onloadstart",
 	"onloadstart",
 	"onmessage",
 	"onmessage",
+	"onmessageerror",
 	"onmousedown",
 	"onmousedown",
+	"onmouseenter",
+	"onmouseleave",
 	"onmousemove",
 	"onmousemove",
 	"onmouseout",
 	"onmouseout",
 	"onmouseover",
 	"onmouseover",
@@ -233,15 +247,18 @@ var testAtomList = []string{
 	"ononline",
 	"ononline",
 	"onpagehide",
 	"onpagehide",
 	"onpageshow",
 	"onpageshow",
+	"onpaste",
 	"onpause",
 	"onpause",
 	"onplay",
 	"onplay",
 	"onplaying",
 	"onplaying",
 	"onpopstate",
 	"onpopstate",
 	"onprogress",
 	"onprogress",
 	"onratechange",
 	"onratechange",
+	"onrejectionhandled",
 	"onreset",
 	"onreset",
 	"onresize",
 	"onresize",
 	"onscroll",
 	"onscroll",
+	"onsecuritypolicyviolation",
 	"onseeked",
 	"onseeked",
 	"onseeking",
 	"onseeking",
 	"onselect",
 	"onselect",
@@ -253,9 +270,11 @@ var testAtomList = []string{
 	"onsuspend",
 	"onsuspend",
 	"ontimeupdate",
 	"ontimeupdate",
 	"ontoggle",
 	"ontoggle",
+	"onunhandledrejection",
 	"onunload",
 	"onunload",
 	"onvolumechange",
 	"onvolumechange",
 	"onwaiting",
 	"onwaiting",
+	"onwheel",
 	"open",
 	"open",
 	"optgroup",
 	"optgroup",
 	"optimum",
 	"optimum",
@@ -264,9 +283,11 @@ var testAtomList = []string{
 	"p",
 	"p",
 	"param",
 	"param",
 	"pattern",
 	"pattern",
+	"picture",
 	"ping",
 	"ping",
 	"placeholder",
 	"placeholder",
 	"plaintext",
 	"plaintext",
+	"playsinline",
 	"poster",
 	"poster",
 	"pre",
 	"pre",
 	"preload",
 	"preload",
@@ -275,7 +296,9 @@ var testAtomList = []string{
 	"public",
 	"public",
 	"q",
 	"q",
 	"radiogroup",
 	"radiogroup",
+	"rb",
 	"readonly",
 	"readonly",
+	"referrerpolicy",
 	"rel",
 	"rel",
 	"required",
 	"required",
 	"reversed",
 	"reversed",
@@ -283,6 +306,7 @@ var testAtomList = []string{
 	"rowspan",
 	"rowspan",
 	"rp",
 	"rp",
 	"rt",
 	"rt",
+	"rtc",
 	"ruby",
 	"ruby",
 	"s",
 	"s",
 	"samp",
 	"samp",
@@ -297,23 +321,23 @@ var testAtomList = []string{
 	"shape",
 	"shape",
 	"size",
 	"size",
 	"sizes",
 	"sizes",
+	"slot",
 	"small",
 	"small",
 	"sortable",
 	"sortable",
 	"sorted",
 	"sorted",
 	"source",
 	"source",
 	"spacer",
 	"spacer",
 	"span",
 	"span",
-	"span",
 	"spellcheck",
 	"spellcheck",
 	"src",
 	"src",
 	"srcdoc",
 	"srcdoc",
 	"srclang",
 	"srclang",
+	"srcset",
 	"start",
 	"start",
 	"step",
 	"step",
 	"strike",
 	"strike",
 	"strong",
 	"strong",
 	"style",
 	"style",
-	"style",
 	"sub",
 	"sub",
 	"summary",
 	"summary",
 	"sup",
 	"sup",
@@ -331,7 +355,6 @@ var testAtomList = []string{
 	"thead",
 	"thead",
 	"time",
 	"time",
 	"title",
 	"title",
-	"title",
 	"tr",
 	"tr",
 	"track",
 	"track",
 	"translate",
 	"translate",
@@ -340,12 +363,14 @@ var testAtomList = []string{
 	"typemustmatch",
 	"typemustmatch",
 	"u",
 	"u",
 	"ul",
 	"ul",
+	"updateviacache",
 	"usemap",
 	"usemap",
 	"value",
 	"value",
 	"var",
 	"var",
 	"video",
 	"video",
 	"wbr",
 	"wbr",
 	"width",
 	"width",
+	"workertype",
 	"wrap",
 	"wrap",
 	"xmp",
 	"xmp",
 }
 }

+ 4 - 2
vendor/golang.org/x/net/html/const.go

@@ -4,7 +4,7 @@
 
 
 package html
 package html
 
 
-// Section 12.2.3.2 of the HTML5 specification says "The following elements
+// Section 12.2.4.2 of the HTML5 specification says "The following elements
 // have varying levels of special parsing rules".
 // have varying levels of special parsing rules".
 // https://html.spec.whatwg.org/multipage/syntax.html#the-stack-of-open-elements
 // https://html.spec.whatwg.org/multipage/syntax.html#the-stack-of-open-elements
 var isSpecialElementMap = map[string]bool{
 var isSpecialElementMap = map[string]bool{
@@ -52,10 +52,12 @@ var isSpecialElementMap = map[string]bool{
 	"iframe":     true,
 	"iframe":     true,
 	"img":        true,
 	"img":        true,
 	"input":      true,
 	"input":      true,
-	"isindex":    true,
+	"isindex":    true, // The 'isindex' element has been removed, but keep it for backwards compatibility.
+	"keygen":     true,
 	"li":         true,
 	"li":         true,
 	"link":       true,
 	"link":       true,
 	"listing":    true,
 	"listing":    true,
+	"main":       true,
 	"marquee":    true,
 	"marquee":    true,
 	"menu":       true,
 	"menu":       true,
 	"meta":       true,
 	"meta":       true,

+ 4 - 4
vendor/golang.org/x/net/html/doc.go

@@ -49,18 +49,18 @@ call to Next. For example, to extract an HTML page's anchor text:
 	for {
 	for {
 		tt := z.Next()
 		tt := z.Next()
 		switch tt {
 		switch tt {
-		case ErrorToken:
+		case html.ErrorToken:
 			return z.Err()
 			return z.Err()
-		case TextToken:
+		case html.TextToken:
 			if depth > 0 {
 			if depth > 0 {
 				// emitBytes should copy the []byte it receives,
 				// emitBytes should copy the []byte it receives,
 				// if it doesn't process it immediately.
 				// if it doesn't process it immediately.
 				emitBytes(z.Text())
 				emitBytes(z.Text())
 			}
 			}
-		case StartTagToken, EndTagToken:
+		case html.StartTagToken, html.EndTagToken:
 			tn, _ := z.TagName()
 			tn, _ := z.TagName()
 			if len(tn) == 1 && tn[0] == 'a' {
 			if len(tn) == 1 && tn[0] == 'a' {
-				if tt == StartTagToken {
+				if tt == html.StartTagToken {
 					depth++
 					depth++
 				} else {
 				} else {
 					depth--
 					depth--

+ 3 - 3
vendor/golang.org/x/net/html/foreign.go

@@ -67,7 +67,7 @@ func mathMLTextIntegrationPoint(n *Node) bool {
 	return false
 	return false
 }
 }
 
 
-// Section 12.2.5.5.
+// Section 12.2.6.5.
 var breakout = map[string]bool{
 var breakout = map[string]bool{
 	"b":          true,
 	"b":          true,
 	"big":        true,
 	"big":        true,
@@ -115,7 +115,7 @@ var breakout = map[string]bool{
 	"var":        true,
 	"var":        true,
 }
 }
 
 
-// Section 12.2.5.5.
+// Section 12.2.6.5.
 var svgTagNameAdjustments = map[string]string{
 var svgTagNameAdjustments = map[string]string{
 	"altglyph":            "altGlyph",
 	"altglyph":            "altGlyph",
 	"altglyphdef":         "altGlyphDef",
 	"altglyphdef":         "altGlyphDef",
@@ -155,7 +155,7 @@ var svgTagNameAdjustments = map[string]string{
 	"textpath":            "textPath",
 	"textpath":            "textPath",
 }
 }
 
 
-// Section 12.2.5.1
+// Section 12.2.6.1
 var mathMLAttributeAdjustments = map[string]string{
 var mathMLAttributeAdjustments = map[string]string{
 	"definitionurl": "definitionURL",
 	"definitionurl": "definitionURL",
 }
 }

+ 30 - 3
vendor/golang.org/x/net/html/node.go

@@ -21,9 +21,10 @@ const (
 	scopeMarkerNode
 	scopeMarkerNode
 )
 )
 
 
-// Section 12.2.3.3 says "scope markers are inserted when entering applet
-// elements, buttons, object elements, marquees, table cells, and table
-// captions, and are used to prevent formatting from 'leaking'".
+// Section 12.2.4.3 says "The markers are inserted when entering applet,
+// object, marquee, template, td, th, and caption elements, and are used
+// to prevent formatting from "leaking" into applet, object, marquee,
+// template, td, th, and caption elements".
 var scopeMarker = Node{Type: scopeMarkerNode}
 var scopeMarker = Node{Type: scopeMarkerNode}
 
 
 // A Node consists of a NodeType and some Data (tag name for element nodes,
 // A Node consists of a NodeType and some Data (tag name for element nodes,
@@ -173,6 +174,16 @@ func (s *nodeStack) index(n *Node) int {
 	return -1
 	return -1
 }
 }
 
 
+// contains returns whether a is within s.
+func (s *nodeStack) contains(a atom.Atom) bool {
+	for _, n := range *s {
+		if n.DataAtom == a {
+			return true
+		}
+	}
+	return false
+}
+
 // insert inserts a node at the given index.
 // insert inserts a node at the given index.
 func (s *nodeStack) insert(i int, n *Node) {
 func (s *nodeStack) insert(i int, n *Node) {
 	(*s) = append(*s, nil)
 	(*s) = append(*s, nil)
@@ -191,3 +202,19 @@ func (s *nodeStack) remove(n *Node) {
 	(*s)[j] = nil
 	(*s)[j] = nil
 	*s = (*s)[:j]
 	*s = (*s)[:j]
 }
 }
+
+type insertionModeStack []insertionMode
+
+func (s *insertionModeStack) pop() (im insertionMode) {
+	i := len(*s)
+	im = (*s)[i-1]
+	*s = (*s)[:i-1]
+	return im
+}
+
+func (s *insertionModeStack) top() insertionMode {
+	if i := len(*s); i > 0 {
+		return (*s)[i-1]
+	}
+	return nil
+}

+ 286 - 75
vendor/golang.org/x/net/html/parse.go

@@ -25,20 +25,22 @@ type parser struct {
 	hasSelfClosingToken bool
 	hasSelfClosingToken bool
 	// doc is the document root element.
 	// doc is the document root element.
 	doc *Node
 	doc *Node
-	// The stack of open elements (section 12.2.3.2) and active formatting
-	// elements (section 12.2.3.3).
+	// The stack of open elements (section 12.2.4.2) and active formatting
+	// elements (section 12.2.4.3).
 	oe, afe nodeStack
 	oe, afe nodeStack
-	// Element pointers (section 12.2.3.4).
+	// Element pointers (section 12.2.4.4).
 	head, form *Node
 	head, form *Node
-	// Other parsing state flags (section 12.2.3.5).
+	// Other parsing state flags (section 12.2.4.5).
 	scripting, framesetOK bool
 	scripting, framesetOK bool
+	// The stack of template insertion modes
+	templateStack insertionModeStack
 	// im is the current insertion mode.
 	// im is the current insertion mode.
 	im insertionMode
 	im insertionMode
 	// originalIM is the insertion mode to go back to after completing a text
 	// originalIM is the insertion mode to go back to after completing a text
 	// or inTableText insertion mode.
 	// or inTableText insertion mode.
 	originalIM insertionMode
 	originalIM insertionMode
 	// fosterParenting is whether new elements should be inserted according to
 	// fosterParenting is whether new elements should be inserted according to
-	// the foster parenting rules (section 12.2.5.3).
+	// the foster parenting rules (section 12.2.6.1).
 	fosterParenting bool
 	fosterParenting bool
 	// quirks is whether the parser is operating in "quirks mode."
 	// quirks is whether the parser is operating in "quirks mode."
 	quirks bool
 	quirks bool
@@ -56,7 +58,7 @@ func (p *parser) top() *Node {
 	return p.doc
 	return p.doc
 }
 }
 
 
-// Stop tags for use in popUntil. These come from section 12.2.3.2.
+// Stop tags for use in popUntil. These come from section 12.2.4.2.
 var (
 var (
 	defaultScopeStopTags = map[string][]a.Atom{
 	defaultScopeStopTags = map[string][]a.Atom{
 		"":     {a.Applet, a.Caption, a.Html, a.Table, a.Td, a.Th, a.Marquee, a.Object, a.Template},
 		"":     {a.Applet, a.Caption, a.Html, a.Table, a.Td, a.Th, a.Marquee, a.Object, a.Template},
@@ -79,7 +81,7 @@ const (
 
 
 // popUntil pops the stack of open elements at the highest element whose tag
 // popUntil pops the stack of open elements at the highest element whose tag
 // is in matchTags, provided there is no higher element in the scope's stop
 // is in matchTags, provided there is no higher element in the scope's stop
-// tags (as defined in section 12.2.3.2). It returns whether or not there was
+// tags (as defined in section 12.2.4.2). It returns whether or not there was
 // such an element. If there was not, popUntil leaves the stack unchanged.
 // such an element. If there was not, popUntil leaves the stack unchanged.
 //
 //
 // For example, the set of stop tags for table scope is: "html", "table". If
 // For example, the set of stop tags for table scope is: "html", "table". If
@@ -126,7 +128,7 @@ func (p *parser) indexOfElementInScope(s scope, matchTags ...a.Atom) int {
 					return -1
 					return -1
 				}
 				}
 			case tableScope:
 			case tableScope:
-				if tagAtom == a.Html || tagAtom == a.Table {
+				if tagAtom == a.Html || tagAtom == a.Table || tagAtom == a.Template {
 					return -1
 					return -1
 				}
 				}
 			case selectScope:
 			case selectScope:
@@ -162,17 +164,17 @@ func (p *parser) clearStackToContext(s scope) {
 		tagAtom := p.oe[i].DataAtom
 		tagAtom := p.oe[i].DataAtom
 		switch s {
 		switch s {
 		case tableScope:
 		case tableScope:
-			if tagAtom == a.Html || tagAtom == a.Table {
+			if tagAtom == a.Html || tagAtom == a.Table || tagAtom == a.Template {
 				p.oe = p.oe[:i+1]
 				p.oe = p.oe[:i+1]
 				return
 				return
 			}
 			}
 		case tableRowScope:
 		case tableRowScope:
-			if tagAtom == a.Html || tagAtom == a.Tr {
+			if tagAtom == a.Html || tagAtom == a.Tr || tagAtom == a.Template {
 				p.oe = p.oe[:i+1]
 				p.oe = p.oe[:i+1]
 				return
 				return
 			}
 			}
 		case tableBodyScope:
 		case tableBodyScope:
-			if tagAtom == a.Html || tagAtom == a.Tbody || tagAtom == a.Tfoot || tagAtom == a.Thead {
+			if tagAtom == a.Html || tagAtom == a.Tbody || tagAtom == a.Tfoot || tagAtom == a.Thead || tagAtom == a.Template {
 				p.oe = p.oe[:i+1]
 				p.oe = p.oe[:i+1]
 				return
 				return
 			}
 			}
@@ -183,7 +185,7 @@ func (p *parser) clearStackToContext(s scope) {
 }
 }
 
 
 // generateImpliedEndTags pops nodes off the stack of open elements as long as
 // generateImpliedEndTags pops nodes off the stack of open elements as long as
-// the top node has a tag name of dd, dt, li, option, optgroup, p, rp, or rt.
+// the top node has a tag name of dd, dt, li, optgroup, option, p, rb, rp, rt or rtc.
 // If exceptions are specified, nodes with that name will not be popped off.
 // If exceptions are specified, nodes with that name will not be popped off.
 func (p *parser) generateImpliedEndTags(exceptions ...string) {
 func (p *parser) generateImpliedEndTags(exceptions ...string) {
 	var i int
 	var i int
@@ -192,7 +194,7 @@ loop:
 		n := p.oe[i]
 		n := p.oe[i]
 		if n.Type == ElementNode {
 		if n.Type == ElementNode {
 			switch n.DataAtom {
 			switch n.DataAtom {
-			case a.Dd, a.Dt, a.Li, a.Option, a.Optgroup, a.P, a.Rp, a.Rt:
+			case a.Dd, a.Dt, a.Li, a.Optgroup, a.Option, a.P, a.Rb, a.Rp, a.Rt, a.Rtc:
 				for _, except := range exceptions {
 				for _, except := range exceptions {
 					if n.Data == except {
 					if n.Data == except {
 						break loop
 						break loop
@@ -207,6 +209,27 @@ loop:
 	p.oe = p.oe[:i+1]
 	p.oe = p.oe[:i+1]
 }
 }
 
 
+// generateAllImpliedEndTags pops nodes off the stack of open elements as long as
+// the top node has a tag name of caption, colgroup, dd, div, dt, li, optgroup, option, p, rb,
+// rp, rt, rtc, span, tbody, td, tfoot, th, thead or tr.
+func (p *parser) generateAllImpliedEndTags() {
+	var i int
+	for i = len(p.oe) - 1; i >= 0; i-- {
+		n := p.oe[i]
+		if n.Type == ElementNode {
+			switch n.DataAtom {
+			// TODO: remove this divergence from the HTML5 spec
+			case a.Caption, a.Colgroup, a.Dd, a.Div, a.Dt, a.Li, a.Optgroup, a.Option, a.P, a.Rb,
+				a.Rp, a.Rt, a.Rtc, a.Span, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr:
+				continue
+			}
+		}
+		break
+	}
+
+	p.oe = p.oe[:i+1]
+}
+
 // addChild adds a child node n to the top element, and pushes n onto the stack
 // addChild adds a child node n to the top element, and pushes n onto the stack
 // of open elements if it is an element node.
 // of open elements if it is an element node.
 func (p *parser) addChild(n *Node) {
 func (p *parser) addChild(n *Node) {
@@ -234,9 +257,9 @@ func (p *parser) shouldFosterParent() bool {
 }
 }
 
 
 // fosterParent adds a child node according to the foster parenting rules.
 // fosterParent adds a child node according to the foster parenting rules.
-// Section 12.2.5.3, "foster parenting".
+// Section 12.2.6.1, "foster parenting".
 func (p *parser) fosterParent(n *Node) {
 func (p *parser) fosterParent(n *Node) {
-	var table, parent, prev *Node
+	var table, parent, prev, template *Node
 	var i int
 	var i int
 	for i = len(p.oe) - 1; i >= 0; i-- {
 	for i = len(p.oe) - 1; i >= 0; i-- {
 		if p.oe[i].DataAtom == a.Table {
 		if p.oe[i].DataAtom == a.Table {
@@ -245,6 +268,19 @@ func (p *parser) fosterParent(n *Node) {
 		}
 		}
 	}
 	}
 
 
+	var j int
+	for j = len(p.oe) - 1; j >= 0; j-- {
+		if p.oe[j].DataAtom == a.Template {
+			template = p.oe[j]
+			break
+		}
+	}
+
+	if template != nil && (table == nil || j < i) {
+		template.AppendChild(n)
+		return
+	}
+
 	if table == nil {
 	if table == nil {
 		// The foster parent is the html element.
 		// The foster parent is the html element.
 		parent = p.oe[0]
 		parent = p.oe[0]
@@ -304,7 +340,7 @@ func (p *parser) addElement() {
 	})
 	})
 }
 }
 
 
-// Section 12.2.3.3.
+// Section 12.2.4.3.
 func (p *parser) addFormattingElement() {
 func (p *parser) addFormattingElement() {
 	tagAtom, attr := p.tok.DataAtom, p.tok.Attr
 	tagAtom, attr := p.tok.DataAtom, p.tok.Attr
 	p.addElement()
 	p.addElement()
@@ -351,7 +387,7 @@ findIdenticalElements:
 	p.afe = append(p.afe, p.top())
 	p.afe = append(p.afe, p.top())
 }
 }
 
 
-// Section 12.2.3.3.
+// Section 12.2.4.3.
 func (p *parser) clearActiveFormattingElements() {
 func (p *parser) clearActiveFormattingElements() {
 	for {
 	for {
 		n := p.afe.pop()
 		n := p.afe.pop()
@@ -361,7 +397,7 @@ func (p *parser) clearActiveFormattingElements() {
 	}
 	}
 }
 }
 
 
-// Section 12.2.3.3.
+// Section 12.2.4.3.
 func (p *parser) reconstructActiveFormattingElements() {
 func (p *parser) reconstructActiveFormattingElements() {
 	n := p.afe.top()
 	n := p.afe.top()
 	if n == nil {
 	if n == nil {
@@ -390,12 +426,12 @@ func (p *parser) reconstructActiveFormattingElements() {
 	}
 	}
 }
 }
 
 
-// Section 12.2.4.
+// Section 12.2.5.
 func (p *parser) acknowledgeSelfClosingTag() {
 func (p *parser) acknowledgeSelfClosingTag() {
 	p.hasSelfClosingToken = false
 	p.hasSelfClosingToken = false
 }
 }
 
 
-// An insertion mode (section 12.2.3.1) is the state transition function from
+// An insertion mode (section 12.2.4.1) is the state transition function from
 // a particular state in the HTML5 parser's state machine. It updates the
 // a particular state in the HTML5 parser's state machine. It updates the
 // parser's fields depending on parser.tok (where ErrorToken means EOF).
 // parser's fields depending on parser.tok (where ErrorToken means EOF).
 // It returns whether the token was consumed.
 // It returns whether the token was consumed.
@@ -403,7 +439,7 @@ type insertionMode func(*parser) bool
 
 
 // setOriginalIM sets the insertion mode to return to after completing a text or
 // setOriginalIM sets the insertion mode to return to after completing a text or
 // inTableText insertion mode.
 // inTableText insertion mode.
-// Section 12.2.3.1, "using the rules for".
+// Section 12.2.4.1, "using the rules for".
 func (p *parser) setOriginalIM() {
 func (p *parser) setOriginalIM() {
 	if p.originalIM != nil {
 	if p.originalIM != nil {
 		panic("html: bad parser state: originalIM was set twice")
 		panic("html: bad parser state: originalIM was set twice")
@@ -411,18 +447,38 @@ func (p *parser) setOriginalIM() {
 	p.originalIM = p.im
 	p.originalIM = p.im
 }
 }
 
 
-// Section 12.2.3.1, "reset the insertion mode".
+// Section 12.2.4.1, "reset the insertion mode".
 func (p *parser) resetInsertionMode() {
 func (p *parser) resetInsertionMode() {
 	for i := len(p.oe) - 1; i >= 0; i-- {
 	for i := len(p.oe) - 1; i >= 0; i-- {
 		n := p.oe[i]
 		n := p.oe[i]
-		if i == 0 && p.context != nil {
+		last := i == 0
+		if last && p.context != nil {
 			n = p.context
 			n = p.context
 		}
 		}
 
 
 		switch n.DataAtom {
 		switch n.DataAtom {
 		case a.Select:
 		case a.Select:
+			if !last {
+				for ancestor, first := n, p.oe[0]; ancestor != first; {
+					if ancestor == first {
+						break
+					}
+					ancestor = p.oe[p.oe.index(ancestor)-1]
+					switch ancestor.DataAtom {
+					case a.Template:
+						p.im = inSelectIM
+						return
+					case a.Table:
+						p.im = inSelectInTableIM
+						return
+					}
+				}
+			}
 			p.im = inSelectIM
 			p.im = inSelectIM
 		case a.Td, a.Th:
 		case a.Td, a.Th:
+			// TODO: remove this divergence from the HTML5 spec.
+			//
+			// See https://bugs.chromium.org/p/chromium/issues/detail?id=829668
 			p.im = inCellIM
 			p.im = inCellIM
 		case a.Tr:
 		case a.Tr:
 			p.im = inRowIM
 			p.im = inRowIM
@@ -434,25 +490,37 @@ func (p *parser) resetInsertionMode() {
 			p.im = inColumnGroupIM
 			p.im = inColumnGroupIM
 		case a.Table:
 		case a.Table:
 			p.im = inTableIM
 			p.im = inTableIM
+		case a.Template:
+			p.im = p.templateStack.top()
 		case a.Head:
 		case a.Head:
-			p.im = inBodyIM
+			// TODO: remove this divergence from the HTML5 spec.
+			//
+			// See https://bugs.chromium.org/p/chromium/issues/detail?id=829668
+			p.im = inHeadIM
 		case a.Body:
 		case a.Body:
 			p.im = inBodyIM
 			p.im = inBodyIM
 		case a.Frameset:
 		case a.Frameset:
 			p.im = inFramesetIM
 			p.im = inFramesetIM
 		case a.Html:
 		case a.Html:
-			p.im = beforeHeadIM
+			if p.head == nil {
+				p.im = beforeHeadIM
+			} else {
+				p.im = afterHeadIM
+			}
 		default:
 		default:
+			if last {
+				p.im = inBodyIM
+				return
+			}
 			continue
 			continue
 		}
 		}
 		return
 		return
 	}
 	}
-	p.im = inBodyIM
 }
 }
 
 
 const whitespace = " \t\r\n\f"
 const whitespace = " \t\r\n\f"
 
 
-// Section 12.2.5.4.1.
+// Section 12.2.6.4.1.
 func initialIM(p *parser) bool {
 func initialIM(p *parser) bool {
 	switch p.tok.Type {
 	switch p.tok.Type {
 	case TextToken:
 	case TextToken:
@@ -479,7 +547,7 @@ func initialIM(p *parser) bool {
 	return false
 	return false
 }
 }
 
 
-// Section 12.2.5.4.2.
+// Section 12.2.6.4.2.
 func beforeHTMLIM(p *parser) bool {
 func beforeHTMLIM(p *parser) bool {
 	switch p.tok.Type {
 	switch p.tok.Type {
 	case DoctypeToken:
 	case DoctypeToken:
@@ -517,7 +585,7 @@ func beforeHTMLIM(p *parser) bool {
 	return false
 	return false
 }
 }
 
 
-// Section 12.2.5.4.3.
+// Section 12.2.6.4.3.
 func beforeHeadIM(p *parser) bool {
 func beforeHeadIM(p *parser) bool {
 	switch p.tok.Type {
 	switch p.tok.Type {
 	case TextToken:
 	case TextToken:
@@ -560,7 +628,7 @@ func beforeHeadIM(p *parser) bool {
 	return false
 	return false
 }
 }
 
 
-// Section 12.2.5.4.4.
+// Section 12.2.6.4.4.
 func inHeadIM(p *parser) bool {
 func inHeadIM(p *parser) bool {
 	switch p.tok.Type {
 	switch p.tok.Type {
 	case TextToken:
 	case TextToken:
@@ -590,19 +658,36 @@ func inHeadIM(p *parser) bool {
 		case a.Head:
 		case a.Head:
 			// Ignore the token.
 			// Ignore the token.
 			return true
 			return true
+		case a.Template:
+			p.addElement()
+			p.afe = append(p.afe, &scopeMarker)
+			p.framesetOK = false
+			p.im = inTemplateIM
+			p.templateStack = append(p.templateStack, inTemplateIM)
+			return true
 		}
 		}
 	case EndTagToken:
 	case EndTagToken:
 		switch p.tok.DataAtom {
 		switch p.tok.DataAtom {
 		case a.Head:
 		case a.Head:
-			n := p.oe.pop()
-			if n.DataAtom != a.Head {
-				panic("html: bad parser state: <head> element not found, in the in-head insertion mode")
-			}
+			p.oe.pop()
 			p.im = afterHeadIM
 			p.im = afterHeadIM
 			return true
 			return true
 		case a.Body, a.Html, a.Br:
 		case a.Body, a.Html, a.Br:
 			p.parseImpliedToken(EndTagToken, a.Head, a.Head.String())
 			p.parseImpliedToken(EndTagToken, a.Head, a.Head.String())
 			return false
 			return false
+		case a.Template:
+			if !p.oe.contains(a.Template) {
+				return true
+			}
+			p.generateAllImpliedEndTags()
+			if n := p.oe.top(); n.DataAtom != a.Template {
+				return true
+			}
+			p.popUntil(defaultScope, a.Template)
+			p.clearActiveFormattingElements()
+			p.templateStack.pop()
+			p.resetInsertionMode()
+			return true
 		default:
 		default:
 			// Ignore the token.
 			// Ignore the token.
 			return true
 			return true
@@ -622,7 +707,7 @@ func inHeadIM(p *parser) bool {
 	return false
 	return false
 }
 }
 
 
-// Section 12.2.5.4.6.
+// Section 12.2.6.4.6.
 func afterHeadIM(p *parser) bool {
 func afterHeadIM(p *parser) bool {
 	switch p.tok.Type {
 	switch p.tok.Type {
 	case TextToken:
 	case TextToken:
@@ -648,7 +733,7 @@ func afterHeadIM(p *parser) bool {
 			p.addElement()
 			p.addElement()
 			p.im = inFramesetIM
 			p.im = inFramesetIM
 			return true
 			return true
-		case a.Base, a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Title:
+		case a.Base, a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Template, a.Title:
 			p.oe = append(p.oe, p.head)
 			p.oe = append(p.oe, p.head)
 			defer p.oe.remove(p.head)
 			defer p.oe.remove(p.head)
 			return inHeadIM(p)
 			return inHeadIM(p)
@@ -660,6 +745,8 @@ func afterHeadIM(p *parser) bool {
 		switch p.tok.DataAtom {
 		switch p.tok.DataAtom {
 		case a.Body, a.Html, a.Br:
 		case a.Body, a.Html, a.Br:
 			// Drop down to creating an implied <body> tag.
 			// Drop down to creating an implied <body> tag.
+		case a.Template:
+			return inHeadIM(p)
 		default:
 		default:
 			// Ignore the token.
 			// Ignore the token.
 			return true
 			return true
@@ -697,7 +784,7 @@ func copyAttributes(dst *Node, src Token) {
 	}
 	}
 }
 }
 
 
-// Section 12.2.5.4.7.
+// Section 12.2.6.4.7.
 func inBodyIM(p *parser) bool {
 func inBodyIM(p *parser) bool {
 	switch p.tok.Type {
 	switch p.tok.Type {
 	case TextToken:
 	case TextToken:
@@ -727,10 +814,16 @@ func inBodyIM(p *parser) bool {
 	case StartTagToken:
 	case StartTagToken:
 		switch p.tok.DataAtom {
 		switch p.tok.DataAtom {
 		case a.Html:
 		case a.Html:
+			if p.oe.contains(a.Template) {
+				return true
+			}
 			copyAttributes(p.oe[0], p.tok)
 			copyAttributes(p.oe[0], p.tok)
-		case a.Base, a.Basefont, a.Bgsound, a.Command, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Title:
+		case a.Base, a.Basefont, a.Bgsound, a.Command, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Template, a.Title:
 			return inHeadIM(p)
 			return inHeadIM(p)
 		case a.Body:
 		case a.Body:
+			if p.oe.contains(a.Template) {
+				return true
+			}
 			if len(p.oe) >= 2 {
 			if len(p.oe) >= 2 {
 				body := p.oe[1]
 				body := p.oe[1]
 				if body.Type == ElementNode && body.DataAtom == a.Body {
 				if body.Type == ElementNode && body.DataAtom == a.Body {
@@ -767,7 +860,7 @@ func inBodyIM(p *parser) bool {
 			// The newline, if any, will be dealt with by the TextToken case.
 			// The newline, if any, will be dealt with by the TextToken case.
 			p.framesetOK = false
 			p.framesetOK = false
 		case a.Form:
 		case a.Form:
-			if p.form == nil {
+			if p.oe.contains(a.Template) || p.form == nil {
 				p.popUntil(buttonScope, a.P)
 				p.popUntil(buttonScope, a.P)
 				p.addElement()
 				p.addElement()
 				p.form = p.top()
 				p.form = p.top()
@@ -952,11 +1045,16 @@ func inBodyIM(p *parser) bool {
 			}
 			}
 			p.reconstructActiveFormattingElements()
 			p.reconstructActiveFormattingElements()
 			p.addElement()
 			p.addElement()
-		case a.Rp, a.Rt:
+		case a.Rb, a.Rtc:
 			if p.elementInScope(defaultScope, a.Ruby) {
 			if p.elementInScope(defaultScope, a.Ruby) {
 				p.generateImpliedEndTags()
 				p.generateImpliedEndTags()
 			}
 			}
 			p.addElement()
 			p.addElement()
+		case a.Rp, a.Rt:
+			if p.elementInScope(defaultScope, a.Ruby) {
+				p.generateImpliedEndTags("rtc")
+			}
+			p.addElement()
 		case a.Math, a.Svg:
 		case a.Math, a.Svg:
 			p.reconstructActiveFormattingElements()
 			p.reconstructActiveFormattingElements()
 			if p.tok.DataAtom == a.Math {
 			if p.tok.DataAtom == a.Math {
@@ -972,7 +1070,13 @@ func inBodyIM(p *parser) bool {
 				p.acknowledgeSelfClosingTag()
 				p.acknowledgeSelfClosingTag()
 			}
 			}
 			return true
 			return true
-		case a.Caption, a.Col, a.Colgroup, a.Frame, a.Head, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr:
+		case a.Frame:
+			// TODO: remove this divergence from the HTML5 spec.
+			if p.oe.contains(a.Template) {
+				p.addElement()
+				return true
+			}
+		case a.Caption, a.Col, a.Colgroup, a.Head, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr:
 			// Ignore the token.
 			// Ignore the token.
 		default:
 		default:
 			p.reconstructActiveFormattingElements()
 			p.reconstructActiveFormattingElements()
@@ -993,15 +1097,28 @@ func inBodyIM(p *parser) bool {
 		case a.Address, a.Article, a.Aside, a.Blockquote, a.Button, a.Center, a.Details, a.Dir, a.Div, a.Dl, a.Fieldset, a.Figcaption, a.Figure, a.Footer, a.Header, a.Hgroup, a.Listing, a.Menu, a.Nav, a.Ol, a.Pre, a.Section, a.Summary, a.Ul:
 		case a.Address, a.Article, a.Aside, a.Blockquote, a.Button, a.Center, a.Details, a.Dir, a.Div, a.Dl, a.Fieldset, a.Figcaption, a.Figure, a.Footer, a.Header, a.Hgroup, a.Listing, a.Menu, a.Nav, a.Ol, a.Pre, a.Section, a.Summary, a.Ul:
 			p.popUntil(defaultScope, p.tok.DataAtom)
 			p.popUntil(defaultScope, p.tok.DataAtom)
 		case a.Form:
 		case a.Form:
-			node := p.form
-			p.form = nil
-			i := p.indexOfElementInScope(defaultScope, a.Form)
-			if node == nil || i == -1 || p.oe[i] != node {
-				// Ignore the token.
-				return true
+			if p.oe.contains(a.Template) {
+				if !p.oe.contains(a.Form) {
+					// Ignore the token.
+					return true
+				}
+				p.generateImpliedEndTags()
+				if p.tok.DataAtom == a.Form {
+					// Ignore the token.
+					return true
+				}
+				p.popUntil(defaultScope, a.Form)
+			} else {
+				node := p.form
+				p.form = nil
+				i := p.indexOfElementInScope(defaultScope, a.Form)
+				if node == nil || i == -1 || p.oe[i] != node {
+					// Ignore the token.
+					return true
+				}
+				p.generateImpliedEndTags()
+				p.oe.remove(node)
 			}
 			}
-			p.generateImpliedEndTags()
-			p.oe.remove(node)
 		case a.P:
 		case a.P:
 			if !p.elementInScope(buttonScope, a.P) {
 			if !p.elementInScope(buttonScope, a.P) {
 				p.parseImpliedToken(StartTagToken, a.P, a.P.String())
 				p.parseImpliedToken(StartTagToken, a.P, a.P.String())
@@ -1022,6 +1139,8 @@ func inBodyIM(p *parser) bool {
 		case a.Br:
 		case a.Br:
 			p.tok.Type = StartTagToken
 			p.tok.Type = StartTagToken
 			return false
 			return false
+		case a.Template:
+			return inHeadIM(p)
 		default:
 		default:
 			p.inBodyEndTagOther(p.tok.DataAtom)
 			p.inBodyEndTagOther(p.tok.DataAtom)
 		}
 		}
@@ -1030,6 +1149,21 @@ func inBodyIM(p *parser) bool {
 			Type: CommentNode,
 			Type: CommentNode,
 			Data: p.tok.Data,
 			Data: p.tok.Data,
 		})
 		})
+	case ErrorToken:
+		// TODO: remove this divergence from the HTML5 spec.
+		if len(p.templateStack) > 0 {
+			p.im = inTemplateIM
+			return false
+		} else {
+			for _, e := range p.oe {
+				switch e.DataAtom {
+				case a.Dd, a.Dt, a.Li, a.Optgroup, a.Option, a.P, a.Rb, a.Rp, a.Rt, a.Rtc, a.Tbody, a.Td, a.Tfoot, a.Th,
+					a.Thead, a.Tr, a.Body, a.Html:
+				default:
+					return true
+				}
+			}
+		}
 	}
 	}
 
 
 	return true
 	return true
@@ -1135,6 +1269,12 @@ func (p *parser) inBodyEndTagFormatting(tagAtom a.Atom) {
 		switch commonAncestor.DataAtom {
 		switch commonAncestor.DataAtom {
 		case a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr:
 		case a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr:
 			p.fosterParent(lastNode)
 			p.fosterParent(lastNode)
+		case a.Template:
+			// TODO: remove namespace checking
+			if commonAncestor.Namespace == "html" {
+				commonAncestor = commonAncestor.LastChild
+			}
+			fallthrough
 		default:
 		default:
 			commonAncestor.AppendChild(lastNode)
 			commonAncestor.AppendChild(lastNode)
 		}
 		}
@@ -1160,7 +1300,7 @@ func (p *parser) inBodyEndTagFormatting(tagAtom a.Atom) {
 }
 }
 
 
 // inBodyEndTagOther performs the "any other end tag" algorithm for inBodyIM.
 // inBodyEndTagOther performs the "any other end tag" algorithm for inBodyIM.
-// "Any other end tag" handling from 12.2.5.5 The rules for parsing tokens in foreign content
+// "Any other end tag" handling from 12.2.6.5 The rules for parsing tokens in foreign content
 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inforeign
 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inforeign
 func (p *parser) inBodyEndTagOther(tagAtom a.Atom) {
 func (p *parser) inBodyEndTagOther(tagAtom a.Atom) {
 	for i := len(p.oe) - 1; i >= 0; i-- {
 	for i := len(p.oe) - 1; i >= 0; i-- {
@@ -1174,7 +1314,7 @@ func (p *parser) inBodyEndTagOther(tagAtom a.Atom) {
 	}
 	}
 }
 }
 
 
-// Section 12.2.5.4.8.
+// Section 12.2.6.4.8.
 func textIM(p *parser) bool {
 func textIM(p *parser) bool {
 	switch p.tok.Type {
 	switch p.tok.Type {
 	case ErrorToken:
 	case ErrorToken:
@@ -1203,7 +1343,7 @@ func textIM(p *parser) bool {
 	return p.tok.Type == EndTagToken
 	return p.tok.Type == EndTagToken
 }
 }
 
 
-// Section 12.2.5.4.9.
+// Section 12.2.6.4.9.
 func inTableIM(p *parser) bool {
 func inTableIM(p *parser) bool {
 	switch p.tok.Type {
 	switch p.tok.Type {
 	case ErrorToken:
 	case ErrorToken:
@@ -1249,7 +1389,7 @@ func inTableIM(p *parser) bool {
 			}
 			}
 			// Ignore the token.
 			// Ignore the token.
 			return true
 			return true
-		case a.Style, a.Script:
+		case a.Style, a.Script, a.Template:
 			return inHeadIM(p)
 			return inHeadIM(p)
 		case a.Input:
 		case a.Input:
 			for _, t := range p.tok.Attr {
 			for _, t := range p.tok.Attr {
@@ -1261,7 +1401,7 @@ func inTableIM(p *parser) bool {
 			}
 			}
 			// Otherwise drop down to the default action.
 			// Otherwise drop down to the default action.
 		case a.Form:
 		case a.Form:
-			if p.form != nil {
+			if p.oe.contains(a.Template) || p.form != nil {
 				// Ignore the token.
 				// Ignore the token.
 				return true
 				return true
 			}
 			}
@@ -1291,6 +1431,8 @@ func inTableIM(p *parser) bool {
 		case a.Body, a.Caption, a.Col, a.Colgroup, a.Html, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr:
 		case a.Body, a.Caption, a.Col, a.Colgroup, a.Html, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr:
 			// Ignore the token.
 			// Ignore the token.
 			return true
 			return true
+		case a.Template:
+			return inHeadIM(p)
 		}
 		}
 	case CommentToken:
 	case CommentToken:
 		p.addChild(&Node{
 		p.addChild(&Node{
@@ -1309,7 +1451,7 @@ func inTableIM(p *parser) bool {
 	return inBodyIM(p)
 	return inBodyIM(p)
 }
 }
 
 
-// Section 12.2.5.4.11.
+// Section 12.2.6.4.11.
 func inCaptionIM(p *parser) bool {
 func inCaptionIM(p *parser) bool {
 	switch p.tok.Type {
 	switch p.tok.Type {
 	case StartTagToken:
 	case StartTagToken:
@@ -1355,7 +1497,7 @@ func inCaptionIM(p *parser) bool {
 	return inBodyIM(p)
 	return inBodyIM(p)
 }
 }
 
 
-// Section 12.2.5.4.12.
+// Section 12.2.6.4.12.
 func inColumnGroupIM(p *parser) bool {
 func inColumnGroupIM(p *parser) bool {
 	switch p.tok.Type {
 	switch p.tok.Type {
 	case TextToken:
 	case TextToken:
@@ -1386,11 +1528,13 @@ func inColumnGroupIM(p *parser) bool {
 			p.oe.pop()
 			p.oe.pop()
 			p.acknowledgeSelfClosingTag()
 			p.acknowledgeSelfClosingTag()
 			return true
 			return true
+		case a.Template:
+			return inHeadIM(p)
 		}
 		}
 	case EndTagToken:
 	case EndTagToken:
 		switch p.tok.DataAtom {
 		switch p.tok.DataAtom {
 		case a.Colgroup:
 		case a.Colgroup:
-			if p.oe.top().DataAtom != a.Html {
+			if p.oe.top().DataAtom == a.Colgroup {
 				p.oe.pop()
 				p.oe.pop()
 				p.im = inTableIM
 				p.im = inTableIM
 			}
 			}
@@ -1398,17 +1542,19 @@ func inColumnGroupIM(p *parser) bool {
 		case a.Col:
 		case a.Col:
 			// Ignore the token.
 			// Ignore the token.
 			return true
 			return true
+		case a.Template:
+			return inHeadIM(p)
 		}
 		}
 	}
 	}
-	if p.oe.top().DataAtom != a.Html {
-		p.oe.pop()
-		p.im = inTableIM
-		return false
+	if p.oe.top().DataAtom != a.Colgroup {
+		return true
 	}
 	}
-	return true
+	p.oe.pop()
+	p.im = inTableIM
+	return false
 }
 }
 
 
-// Section 12.2.5.4.13.
+// Section 12.2.6.4.13.
 func inTableBodyIM(p *parser) bool {
 func inTableBodyIM(p *parser) bool {
 	switch p.tok.Type {
 	switch p.tok.Type {
 	case StartTagToken:
 	case StartTagToken:
@@ -1460,7 +1606,7 @@ func inTableBodyIM(p *parser) bool {
 	return inTableIM(p)
 	return inTableIM(p)
 }
 }
 
 
-// Section 12.2.5.4.14.
+// Section 12.2.6.4.14.
 func inRowIM(p *parser) bool {
 func inRowIM(p *parser) bool {
 	switch p.tok.Type {
 	switch p.tok.Type {
 	case StartTagToken:
 	case StartTagToken:
@@ -1511,7 +1657,7 @@ func inRowIM(p *parser) bool {
 	return inTableIM(p)
 	return inTableIM(p)
 }
 }
 
 
-// Section 12.2.5.4.15.
+// Section 12.2.6.4.15.
 func inCellIM(p *parser) bool {
 func inCellIM(p *parser) bool {
 	switch p.tok.Type {
 	switch p.tok.Type {
 	case StartTagToken:
 	case StartTagToken:
@@ -1560,7 +1706,7 @@ func inCellIM(p *parser) bool {
 	return inBodyIM(p)
 	return inBodyIM(p)
 }
 }
 
 
-// Section 12.2.5.4.16.
+// Section 12.2.6.4.16.
 func inSelectIM(p *parser) bool {
 func inSelectIM(p *parser) bool {
 	switch p.tok.Type {
 	switch p.tok.Type {
 	case ErrorToken:
 	case ErrorToken:
@@ -1597,7 +1743,7 @@ func inSelectIM(p *parser) bool {
 			p.tokenizer.NextIsNotRawText()
 			p.tokenizer.NextIsNotRawText()
 			// Ignore the token.
 			// Ignore the token.
 			return true
 			return true
-		case a.Script:
+		case a.Script, a.Template:
 			return inHeadIM(p)
 			return inHeadIM(p)
 		}
 		}
 	case EndTagToken:
 	case EndTagToken:
@@ -1618,6 +1764,8 @@ func inSelectIM(p *parser) bool {
 			if p.popUntil(selectScope, a.Select) {
 			if p.popUntil(selectScope, a.Select) {
 				p.resetInsertionMode()
 				p.resetInsertionMode()
 			}
 			}
+		case a.Template:
+			return inHeadIM(p)
 		}
 		}
 	case CommentToken:
 	case CommentToken:
 		p.addChild(&Node{
 		p.addChild(&Node{
@@ -1632,7 +1780,7 @@ func inSelectIM(p *parser) bool {
 	return true
 	return true
 }
 }
 
 
-// Section 12.2.5.4.17.
+// Section 12.2.6.4.17.
 func inSelectInTableIM(p *parser) bool {
 func inSelectInTableIM(p *parser) bool {
 	switch p.tok.Type {
 	switch p.tok.Type {
 	case StartTagToken, EndTagToken:
 	case StartTagToken, EndTagToken:
@@ -1650,7 +1798,62 @@ func inSelectInTableIM(p *parser) bool {
 	return inSelectIM(p)
 	return inSelectIM(p)
 }
 }
 
 
-// Section 12.2.5.4.18.
+// Section 12.2.6.4.18.
+func inTemplateIM(p *parser) bool {
+	switch p.tok.Type {
+	case TextToken, CommentToken, DoctypeToken:
+		return inBodyIM(p)
+	case StartTagToken:
+		switch p.tok.DataAtom {
+		case a.Base, a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Template, a.Title:
+			return inHeadIM(p)
+		case a.Caption, a.Colgroup, a.Tbody, a.Tfoot, a.Thead:
+			p.templateStack.pop()
+			p.templateStack = append(p.templateStack, inTableIM)
+			p.im = inTableIM
+			return false
+		case a.Col:
+			p.templateStack.pop()
+			p.templateStack = append(p.templateStack, inColumnGroupIM)
+			p.im = inColumnGroupIM
+			return false
+		case a.Tr:
+			p.templateStack.pop()
+			p.templateStack = append(p.templateStack, inTableBodyIM)
+			p.im = inTableBodyIM
+			return false
+		case a.Td, a.Th:
+			p.templateStack.pop()
+			p.templateStack = append(p.templateStack, inRowIM)
+			p.im = inRowIM
+			return false
+		default:
+			p.templateStack.pop()
+			p.templateStack = append(p.templateStack, inBodyIM)
+			p.im = inBodyIM
+			return false
+		}
+	case EndTagToken:
+		switch p.tok.DataAtom {
+		case a.Template:
+			return inHeadIM(p)
+		default:
+			// Ignore the token.
+			return true
+		}
+	}
+	if !p.oe.contains(a.Template) {
+		// Ignore the token.
+		return true
+	}
+	p.popUntil(defaultScope, a.Template)
+	p.clearActiveFormattingElements()
+	p.templateStack.pop()
+	p.resetInsertionMode()
+	return false
+}
+
+// Section 12.2.6.4.19.
 func afterBodyIM(p *parser) bool {
 func afterBodyIM(p *parser) bool {
 	switch p.tok.Type {
 	switch p.tok.Type {
 	case ErrorToken:
 	case ErrorToken:
@@ -1688,7 +1891,7 @@ func afterBodyIM(p *parser) bool {
 	return false
 	return false
 }
 }
 
 
-// Section 12.2.5.4.19.
+// Section 12.2.6.4.20.
 func inFramesetIM(p *parser) bool {
 func inFramesetIM(p *parser) bool {
 	switch p.tok.Type {
 	switch p.tok.Type {
 	case CommentToken:
 	case CommentToken:
@@ -1720,6 +1923,11 @@ func inFramesetIM(p *parser) bool {
 			p.acknowledgeSelfClosingTag()
 			p.acknowledgeSelfClosingTag()
 		case a.Noframes:
 		case a.Noframes:
 			return inHeadIM(p)
 			return inHeadIM(p)
+		case a.Template:
+			// TODO: remove this divergence from the HTML5 spec.
+			//
+			// See https://bugs.chromium.org/p/chromium/issues/detail?id=829668
+			return inTemplateIM(p)
 		}
 		}
 	case EndTagToken:
 	case EndTagToken:
 		switch p.tok.DataAtom {
 		switch p.tok.DataAtom {
@@ -1738,7 +1946,7 @@ func inFramesetIM(p *parser) bool {
 	return true
 	return true
 }
 }
 
 
-// Section 12.2.5.4.20.
+// Section 12.2.6.4.21.
 func afterFramesetIM(p *parser) bool {
 func afterFramesetIM(p *parser) bool {
 	switch p.tok.Type {
 	switch p.tok.Type {
 	case CommentToken:
 	case CommentToken:
@@ -1777,7 +1985,7 @@ func afterFramesetIM(p *parser) bool {
 	return true
 	return true
 }
 }
 
 
-// Section 12.2.5.4.21.
+// Section 12.2.6.4.22.
 func afterAfterBodyIM(p *parser) bool {
 func afterAfterBodyIM(p *parser) bool {
 	switch p.tok.Type {
 	switch p.tok.Type {
 	case ErrorToken:
 	case ErrorToken:
@@ -1806,7 +2014,7 @@ func afterAfterBodyIM(p *parser) bool {
 	return false
 	return false
 }
 }
 
 
-// Section 12.2.5.4.22.
+// Section 12.2.6.4.23.
 func afterAfterFramesetIM(p *parser) bool {
 func afterAfterFramesetIM(p *parser) bool {
 	switch p.tok.Type {
 	switch p.tok.Type {
 	case CommentToken:
 	case CommentToken:
@@ -1844,7 +2052,7 @@ func afterAfterFramesetIM(p *parser) bool {
 
 
 const whitespaceOrNUL = whitespace + "\x00"
 const whitespaceOrNUL = whitespace + "\x00"
 
 
-// Section 12.2.5.5.
+// Section 12.2.6.5
 func parseForeignContent(p *parser) bool {
 func parseForeignContent(p *parser) bool {
 	switch p.tok.Type {
 	switch p.tok.Type {
 	case TextToken:
 	case TextToken:
@@ -1924,7 +2132,7 @@ func parseForeignContent(p *parser) bool {
 	return true
 	return true
 }
 }
 
 
-// Section 12.2.5.
+// Section 12.2.6.
 func (p *parser) inForeignContent() bool {
 func (p *parser) inForeignContent() bool {
 	if len(p.oe) == 0 {
 	if len(p.oe) == 0 {
 		return false
 		return false
@@ -2064,6 +2272,9 @@ func ParseFragment(r io.Reader, context *Node) ([]*Node, error) {
 	}
 	}
 	p.doc.AppendChild(root)
 	p.doc.AppendChild(root)
 	p.oe = nodeStack{root}
 	p.oe = nodeStack{root}
+	if context != nil && context.DataAtom == a.Template {
+		p.templateStack = append(p.templateStack, inTemplateIM)
+	}
 	p.resetInsertionMode()
 	p.resetInsertionMode()
 
 
 	for n := context; n != nil; n = n.Parent {
 	for n := context; n != nil; n = n.Parent {

+ 14 - 2
vendor/golang.org/x/net/html/parse_test.go

@@ -125,6 +125,7 @@ func (a sortedAttributes) Swap(i, j int) {
 
 
 func dumpLevel(w io.Writer, n *Node, level int) error {
 func dumpLevel(w io.Writer, n *Node, level int) error {
 	dumpIndent(w, level)
 	dumpIndent(w, level)
+	level++
 	switch n.Type {
 	switch n.Type {
 	case ErrorNode:
 	case ErrorNode:
 		return errors.New("unexpected ErrorNode")
 		return errors.New("unexpected ErrorNode")
@@ -140,13 +141,19 @@ func dumpLevel(w io.Writer, n *Node, level int) error {
 		sort.Sort(attr)
 		sort.Sort(attr)
 		for _, a := range attr {
 		for _, a := range attr {
 			io.WriteString(w, "\n")
 			io.WriteString(w, "\n")
-			dumpIndent(w, level+1)
+			dumpIndent(w, level)
 			if a.Namespace != "" {
 			if a.Namespace != "" {
 				fmt.Fprintf(w, `%s %s="%s"`, a.Namespace, a.Key, a.Val)
 				fmt.Fprintf(w, `%s %s="%s"`, a.Namespace, a.Key, a.Val)
 			} else {
 			} else {
 				fmt.Fprintf(w, `%s="%s"`, a.Key, a.Val)
 				fmt.Fprintf(w, `%s="%s"`, a.Key, a.Val)
 			}
 			}
 		}
 		}
+		if n.Namespace == "" && n.DataAtom == atom.Template {
+			io.WriteString(w, "\n")
+			dumpIndent(w, level)
+			level++
+			io.WriteString(w, "content")
+		}
 	case TextNode:
 	case TextNode:
 		fmt.Fprintf(w, `"%s"`, n.Data)
 		fmt.Fprintf(w, `"%s"`, n.Data)
 	case CommentNode:
 	case CommentNode:
@@ -176,7 +183,7 @@ func dumpLevel(w io.Writer, n *Node, level int) error {
 	}
 	}
 	io.WriteString(w, "\n")
 	io.WriteString(w, "\n")
 	for c := n.FirstChild; c != nil; c = c.NextSibling {
 	for c := n.FirstChild; c != nil; c = c.NextSibling {
-		if err := dumpLevel(w, c, level+1); err != nil {
+		if err := dumpLevel(w, c, level); err != nil {
 			return err
 			return err
 		}
 		}
 	}
 	}
@@ -373,6 +380,11 @@ func TestNodeConsistency(t *testing.T) {
 	}
 	}
 }
 }
 
 
+func TestParseFragmentWithNilContext(t *testing.T) {
+	// This shouldn't panic.
+	ParseFragment(strings.NewReader("<p>hello</p>"), nil)
+}
+
 func BenchmarkParser(b *testing.B) {
 func BenchmarkParser(b *testing.B) {
 	buf, err := ioutil.ReadFile("testdata/go1.html")
 	buf, err := ioutil.ReadFile("testdata/go1.html")
 	if err != nil {
 	if err != nil {

+ 298 - 0
vendor/golang.org/x/net/html/testdata/webkit/ruby.dat

@@ -0,0 +1,298 @@
+#data
+<html><ruby>a<rb>b<rb></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+|   <head>
+|   <body>
+|     <ruby>
+|       "a"
+|       <rb>
+|         "b"
+|       <rb>
+
+#data
+<html><ruby>a<rb>b<rt></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+|   <head>
+|   <body>
+|     <ruby>
+|       "a"
+|       <rb>
+|         "b"
+|       <rt>
+
+#data
+<html><ruby>a<rb>b<rtc></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+|   <head>
+|   <body>
+|     <ruby>
+|       "a"
+|       <rb>
+|         "b"
+|       <rtc>
+
+#data
+<html><ruby>a<rb>b<rp></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+|   <head>
+|   <body>
+|     <ruby>
+|       "a"
+|       <rb>
+|         "b"
+|       <rp>
+
+#data
+<html><ruby>a<rb>b<span></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+|   <head>
+|   <body>
+|     <ruby>
+|       "a"
+|       <rb>
+|         "b"
+|         <span>
+
+#data
+<html><ruby>a<rt>b<rb></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+|   <head>
+|   <body>
+|     <ruby>
+|       "a"
+|       <rt>
+|         "b"
+|       <rb>
+
+#data
+<html><ruby>a<rt>b<rt></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+|   <head>
+|   <body>
+|     <ruby>
+|       "a"
+|       <rt>
+|         "b"
+|       <rt>
+
+#data
+<html><ruby>a<rt>b<rtc></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+|   <head>
+|   <body>
+|     <ruby>
+|       "a"
+|       <rt>
+|         "b"
+|       <rtc>
+
+#data
+<html><ruby>a<rt>b<rp></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+|   <head>
+|   <body>
+|     <ruby>
+|       "a"
+|       <rt>
+|         "b"
+|       <rp>
+
+#data
+<html><ruby>a<rt>b<span></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+|   <head>
+|   <body>
+|     <ruby>
+|       "a"
+|       <rt>
+|         "b"
+|         <span>
+
+#data
+<html><ruby>a<rtc>b<rb></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+|   <head>
+|   <body>
+|     <ruby>
+|       "a"
+|       <rtc>
+|         "b"
+|       <rb>
+
+#data
+<html><ruby>a<rtc>b<rt>c<rt>d</ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+|   <head>
+|   <body>
+|     <ruby>
+|       "a"
+|       <rtc>
+|         "b"
+|         <rt>
+|           "c"
+|         <rt>
+|           "d"
+
+#data
+<html><ruby>a<rtc>b<rtc></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+|   <head>
+|   <body>
+|     <ruby>
+|       "a"
+|       <rtc>
+|         "b"
+|       <rtc>
+
+#data
+<html><ruby>a<rtc>b<rp></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+|   <head>
+|   <body>
+|     <ruby>
+|       "a"
+|       <rtc>
+|         "b"
+|         <rp>
+
+#data
+<html><ruby>a<rtc>b<span></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+|   <head>
+|   <body>
+|     <ruby>
+|       "a"
+|       <rtc>
+|         "b"
+|         <span>
+
+#data
+<html><ruby>a<rp>b<rb></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+|   <head>
+|   <body>
+|     <ruby>
+|       "a"
+|       <rp>
+|         "b"
+|       <rb>
+
+#data
+<html><ruby>a<rp>b<rt></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+|   <head>
+|   <body>
+|     <ruby>
+|       "a"
+|       <rp>
+|         "b"
+|       <rt>
+
+#data
+<html><ruby>a<rp>b<rtc></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+|   <head>
+|   <body>
+|     <ruby>
+|       "a"
+|       <rp>
+|         "b"
+|       <rtc>
+
+#data
+<html><ruby>a<rp>b<rp></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+|   <head>
+|   <body>
+|     <ruby>
+|       "a"
+|       <rp>
+|         "b"
+|       <rp>
+
+#data
+<html><ruby>a<rp>b<span></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+|   <head>
+|   <body>
+|     <ruby>
+|       "a"
+|       <rp>
+|         "b"
+|         <span>
+
+#data
+<html><ruby><rtc><ruby>a<rb>b<rt></ruby></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+|   <head>
+|   <body>
+|     <ruby>
+|       <rtc>
+|         <ruby>
+|           "a"
+|           <rb>
+|             "b"
+|           <rt>

+ 1117 - 0
vendor/golang.org/x/net/html/testdata/webkit/template.dat

@@ -0,0 +1,1117 @@
+#data
+<body><template>Hello</template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       content
+|         "Hello"
+
+#data
+<template>Hello</template>
+#errors
+#document
+| <html>
+|   <head>
+|     <template>
+|       content
+|         "Hello"
+|   <body>
+
+#data
+<template></template><div></div>
+#errors
+#document
+| <html>
+|   <head>
+|     <template>
+|       content
+|   <body>
+|     <div>
+
+#data
+<html><template>Hello</template>
+#errors
+#document
+| <html>
+|   <head>
+|     <template>
+|       content
+|         "Hello"
+|   <body>
+
+#data
+<head><template><div></div></template></head>
+#errors
+#document
+| <html>
+|   <head>
+|     <template>
+|       content
+|         <div>
+|   <body>
+
+#data
+<div><template><div><span></template><b>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <div>
+|       <template>
+|         content
+|           <div>
+|             <span>
+|       <b>
+
+#data
+<div><template></div>Hello
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <div>
+|       <template>
+|         content
+|           "Hello"
+
+#data
+<div></template></div>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <div>
+
+#data
+<table><template></template></table>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <template>
+|         content
+
+#data
+<table><template></template></div>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <template>
+|         content
+
+#data
+<table><div><template></template></div>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <div>
+|       <template>
+|         content
+|     <table>
+
+#data
+<table><template></template><div></div>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <div>
+|     <table>
+|       <template>
+|         content
+
+#data
+<table>   <template></template></table>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       "   "
+|       <template>
+|         content
+
+#data
+<table><tbody><template></template></tbody>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <tbody>
+|         <template>
+|           content
+
+#data
+<table><tbody><template></tbody></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <tbody>
+|         <template>
+|           content
+
+#data
+<table><tbody><template></template></tbody></table>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <tbody>
+|         <template>
+|           content
+
+#data
+<table><thead><template></template></thead>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <thead>
+|         <template>
+|           content
+
+#data
+<table><tfoot><template></template></tfoot>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <tfoot>
+|         <template>
+|           content
+
+#data
+<select><template></template></select>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <select>
+|       <template>
+|         content
+
+#data
+<select><template><option></option></template></select>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <select>
+|       <template>
+|         content
+|           <option>
+
+#data
+<template><option></option></select><option></option></template>
+#errors
+#document
+| <html>
+|   <head>
+|     <template>
+|       content
+|         <option>
+|         <option>
+|   <body>
+
+#data
+<select><template></template><option></select>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <select>
+|       <template>
+|         content
+|       <option>
+
+#data
+<select><option><template></template></select>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <select>
+|       <option>
+|         <template>
+|           content
+
+#data
+<select><template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <select>
+|       <template>
+|         content
+
+#data
+<select><option></option><template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <select>
+|       <option>
+|       <template>
+|         content
+
+#data
+<select><option></option><template><option>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <select>
+|       <option>
+|       <template>
+|         content
+|           <option>
+
+#data
+<table><thead><template><td></template></table>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <thead>
+|         <template>
+|           content
+|             <td>
+
+#data
+<table><template><thead></template></table>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <template>
+|         content
+|           <thead>
+
+#data
+<body><table><template><td></tr><div></template></table>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <template>
+|         content
+|           <td>
+|             <div>
+
+#data
+<table><template><thead></template></thead></table>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <template>
+|         content
+|           <thead>
+
+#data
+<table><thead><template><tr></template></table>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <thead>
+|         <template>
+|           content
+|             <tr>
+
+#data
+<table><template><tr></template></table>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <template>
+|         content
+|           <tr>
+
+#data
+<table><tr><template><td>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <tbody>
+|         <tr>
+|           <template>
+|             content
+|               <td>
+
+#data
+<table><template><tr><template><td></template></tr></template></table>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <template>
+|         content
+|           <tr>
+|             <template>
+|               content
+|                 <td>
+
+#data
+<table><template><tr><template><td></td></template></tr></template></table>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <template>
+|         content
+|           <tr>
+|             <template>
+|               content
+|                 <td>
+
+#data
+<table><template><td></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <template>
+|         content
+|           <td>
+
+#data
+<body><template><td></td></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       content
+|         <td>
+
+#data
+<body><template><template><tr></tr></template><td></td></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       content
+|         <template>
+|           content
+|             <tr>
+|         <td>
+
+#data
+<table><colgroup><template><col>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <colgroup>
+|         <template>
+|           content
+|             <col>
+
+#data
+<frameset><template><frame></frame></template></frameset>
+#errors
+#document
+| <html>
+|   <head>
+|   <frameset>
+|     <template>
+|       content
+|         <frame>
+
+#data
+<template><frame></frame></frameset><frame></frame></template>
+#errors
+#document
+| <html>
+|   <head>
+|     <template>
+|       content
+|         <frame>
+|         <frame>
+|   <body>
+
+#data
+<template><div><frameset><span></span></div><span></span></template>
+#errors
+#document
+| <html>
+|   <head>
+|     <template>
+|       content
+|         <div>
+|           <span>
+|         <span>
+|   <body>
+
+#data
+<body><template><div><frameset><span></span></div><span></span></template></body>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       content
+|         <div>
+|           <span>
+|         <span>
+
+#data
+<body><template><script>var i = 1;</script><td></td></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       content
+|         <script>
+|           "var i = 1;"
+|         <td>
+
+#data
+<body><template><tr><div></div></tr></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       content
+|         <tr>
+|         <div>
+
+#data
+<body><template><tr></tr><td></td></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       content
+|         <tr>
+|         <tr>
+|           <td>
+
+#data
+<body><template><td></td></tr><td></td></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       content
+|         <td>
+|         <td>
+
+#data
+<body><template><td></td><tbody><td></td></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       content
+|         <td>
+|         <td>
+
+#data
+<body><template><td></td><caption></caption><td></td></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       content
+|         <td>
+|         <td>
+
+#data
+<body><template><td></td><colgroup></caption><td></td></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       content
+|         <td>
+|         <td>
+
+#data
+<body><template><td></td></table><td></td></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       content
+|         <td>
+|         <td>
+
+#data
+<body><template><tr></tr><tbody><tr></tr></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       content
+|         <tr>
+|         <tr>
+
+#data
+<body><template><tr></tr><caption><tr></tr></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       content
+|         <tr>
+|         <tr>
+
+#data
+<body><template><tr></tr></table><tr></tr></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       content
+|         <tr>
+|         <tr>
+
+#data
+<body><template><thead></thead><caption></caption><tbody></tbody></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       content
+|         <thead>
+|         <caption>
+|         <tbody>
+
+#data
+<body><template><thead></thead></table><tbody></tbody></template></body>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       content
+|         <thead>
+|         <tbody>
+
+#data
+<body><template><div><tr></tr></div></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       content
+|         <div>
+
+#data
+<body><template><em>Hello</em></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       content
+|         <em>
+|           "Hello"
+
+#data
+<body><template><!--comment--></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       content
+|         <!-- comment -->
+
+#data
+<body><template><style></style><td></td></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       content
+|         <style>
+|         <td>
+
+#data
+<body><template><meta><td></td></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       content
+|         <meta>
+|         <td>
+
+#data
+<body><template><link><td></td></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       content
+|         <link>
+|         <td>
+
+#data
+<body><template><template><tr></tr></template><td></td></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       content
+|         <template>
+|           content
+|             <tr>
+|         <td>
+
+#data
+<body><table><colgroup><template><col></col></template></colgroup></table></body>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <colgroup>
+|         <template>
+|           content
+|             <col>
+
+#data
+<body a=b><template><div></div><body c=d><div></div></body></template></body>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     a="b"
+|     <template>
+|       content
+|         <div>
+|         <div>
+
+#data
+<html a=b><template><div><html b=c><span></template>
+#errors
+#document
+| <html>
+|   a="b"
+|   <head>
+|     <template>
+|       content
+|         <div>
+|           <span>
+|   <body>
+
+#data
+<html a=b><template><col></col><html b=c><col></col></template>
+#errors
+#document
+| <html>
+|   a="b"
+|   <head>
+|     <template>
+|       content
+|         <col>
+|         <col>
+|   <body>
+
+#data
+<html a=b><template><frame></frame><html b=c><frame></frame></template>
+#errors
+#document
+| <html>
+|   a="b"
+|   <head>
+|     <template>
+|       content
+|         <frame>
+|         <frame>
+|   <body>
+
+#data
+<body><template><tr></tr><template></template><td></td></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       content
+|         <tr>
+|         <template>
+|           content
+|         <tr>
+|           <td>
+
+#data
+<body><template><thead></thead><template><tr></tr></template><tr></tr><tfoot></tfoot></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       content
+|         <thead>
+|         <template>
+|           content
+|             <tr>
+|         <tbody>
+|           <tr>
+|         <tfoot>
+
+#data
+<body><template><col><colgroup>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       content
+|         <col>
+
+#data
+<body><template><col></colgroup>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       content
+|         <col>
+
+#data
+<body><template><col><colgroup></template></body>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       content
+|         <col>
+
+#data
+<body><template><col><div>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       content
+|         <col>
+
+#data
+<body><template><col></div>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       content
+|         <col>
+
+#data
+<body><template><col>Hello
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       content
+|         <col>
+
+#data
+<body><template><i><menu>Foo</i>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       content
+|         <i>
+|         <menu>
+|           <i>
+|             "Foo"
+
+#data
+<body><template></div><div>Foo</div><template></template><tr></tr>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       content
+|         <div>
+|           "Foo"
+|         <template>
+|           content
+
+#data
+<body><div><template></div><tr><td>Foo</td></tr></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <div>
+|       <template>
+|         content
+|           <tr>
+|             <td>
+|               "Foo"
+
+#data
+<template></figcaption><sub><table></table>
+#errors
+#document
+| <html>
+|   <head>
+|     <template>
+|       content
+|         <sub>
+|           <table>
+|   <body>
+
+#data
+<template><template>
+#errors
+#document
+| <html>
+|   <head>
+|     <template>
+|       content
+|         <template>
+|           content
+|   <body>
+
+#data
+<template><div>
+#errors
+#document
+| <html>
+|   <head>
+|     <template>
+|       content
+|         <div>
+|   <body>
+
+#data
+<template><template><div>
+#errors
+#document
+| <html>
+|   <head>
+|     <template>
+|       content
+|         <template>
+|           content
+|             <div>
+|   <body>
+
+#data
+<template><template><script>var i
+#errors
+#document
+| <html>
+|   <head>
+|     <template>
+|       content
+|         <template>
+|           content
+|             <script>
+|               "var i"
+|   <body>
+
+#data
+<template><template><style>var i
+#errors
+#document
+| <html>
+|   <head>
+|     <template>
+|       content
+|         <template>
+|           content
+|             <style>
+|               "var i"
+|   <body>
+
+#data
+<template><svg><template>
+#errors
+#document
+| <html>
+|   <head>
+|     <template>
+|       content
+|         <svg svg>
+|           <svg template>
+|   <body>
+
+#data
+<dummy><template><span></dummy>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <dummy>
+|       <template>
+|         content
+|           <span>
+
+#data
+<body><table><tr><td><select><template>Foo</template><caption>A</table>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <tbody>
+|         <tr>
+|           <td>
+|             <select>
+|               <template>
+|                 content
+|                   "Foo"
+|       <caption>
+|         "A"
+
+#data
+<body></body><template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       content
+
+#data
+<head></head><template>
+#errors
+#document
+| <html>
+|   <head>
+|     <template>
+|       content
+|   <body>
+
+#data
+<head></head><template>Foo</template>
+#errors
+#document
+| <html>
+|   <head>
+|     <template>
+|       content
+|         "Foo"
+|   <body>

+ 2 - 2
vendor/golang.org/x/net/html/token.go

@@ -1161,8 +1161,8 @@ func (z *Tokenizer) TagAttr() (key, val []byte, moreAttr bool) {
 	return nil, nil, false
 	return nil, nil, false
 }
 }
 
 
-// Token returns the next Token. The result's Data and Attr values remain valid
-// after subsequent Next calls.
+// Token returns the current Token. The result's Data and Attr values remain
+// valid after subsequent Next calls.
 func (z *Tokenizer) Token() Token {
 func (z *Tokenizer) Token() Token {
 	t := Token{Type: z.tt}
 	t := Token{Type: z.tt}
 	switch z.tt {
 	switch z.tt {

+ 50 - 0
vendor/golang.org/x/net/http/httpguts/guts.go

@@ -0,0 +1,50 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package httpguts provides functions implementing various details
+// of the HTTP specification.
+//
+// This package is shared by the standard library (which vendors it)
+// and x/net/http2. It comes with no API stability promise.
+package httpguts
+
+import (
+	"net/textproto"
+	"strings"
+)
+
+// ValidTrailerHeader reports whether name is a valid header field name to appear
+// in trailers.
+// See RFC 7230, Section 4.1.2
+func ValidTrailerHeader(name string) bool {
+	name = textproto.CanonicalMIMEHeaderKey(name)
+	if strings.HasPrefix(name, "If-") || badTrailer[name] {
+		return false
+	}
+	return true
+}
+
+var badTrailer = map[string]bool{
+	"Authorization":       true,
+	"Cache-Control":       true,
+	"Connection":          true,
+	"Content-Encoding":    true,
+	"Content-Length":      true,
+	"Content-Range":       true,
+	"Content-Type":        true,
+	"Expect":              true,
+	"Host":                true,
+	"Keep-Alive":          true,
+	"Max-Forwards":        true,
+	"Pragma":              true,
+	"Proxy-Authenticate":  true,
+	"Proxy-Authorization": true,
+	"Proxy-Connection":    true,
+	"Range":               true,
+	"Realm":               true,
+	"Te":                  true,
+	"Trailer":             true,
+	"Transfer-Encoding":   true,
+	"Www-Authenticate":    true,
+}

+ 7 - 0
vendor/golang.org/x/net/http/httpproxy/export_test.go

@@ -0,0 +1,7 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package httpproxy
+
+var ExportUseProxy = (*Config).useProxy

+ 13 - 0
vendor/golang.org/x/net/http/httpproxy/go19_test.go

@@ -0,0 +1,13 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.9
+
+package httpproxy_test
+
+import "testing"
+
+func init() {
+	setHelper = func(t *testing.T) { t.Helper() }
+}

+ 239 - 0
vendor/golang.org/x/net/http/httpproxy/proxy.go

@@ -0,0 +1,239 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package httpproxy provides support for HTTP proxy determination
+// based on environment variables, as provided by net/http's
+// ProxyFromEnvironment function.
+//
+// The API is not subject to the Go 1 compatibility promise and may change at
+// any time.
+package httpproxy
+
+import (
+	"errors"
+	"fmt"
+	"net"
+	"net/url"
+	"os"
+	"strings"
+	"unicode/utf8"
+
+	"golang.org/x/net/idna"
+)
+
+// Config holds configuration for HTTP proxy settings. See
+// FromEnvironment for details.
+type Config struct {
+	// HTTPProxy represents the value of the HTTP_PROXY or
+	// http_proxy environment variable. It will be used as the proxy
+	// URL for HTTP requests and HTTPS requests unless overridden by
+	// HTTPSProxy or NoProxy.
+	HTTPProxy string
+
+	// HTTPSProxy represents the HTTPS_PROXY or https_proxy
+	// environment variable. It will be used as the proxy URL for
+	// HTTPS requests unless overridden by NoProxy.
+	HTTPSProxy string
+
+	// NoProxy represents the NO_PROXY or no_proxy environment
+	// variable. It specifies URLs that should be excluded from
+	// proxying as a comma-separated list of domain names or a
+	// single asterisk (*) to indicate that no proxying should be
+	// done. A domain name matches that name and all subdomains. A
+	// domain name with a leading "." matches subdomains only. For
+	// example "foo.com" matches "foo.com" and "bar.foo.com";
+	// ".y.com" matches "x.y.com" but not "y.com".
+	NoProxy string
+
+	// CGI holds whether the current process is running
+	// as a CGI handler (FromEnvironment infers this from the
+	// presence of a REQUEST_METHOD environment variable).
+	// When this is set, ProxyForURL will return an error
+	// when HTTPProxy applies, because a client could be
+	// setting HTTP_PROXY maliciously. See https://golang.org/s/cgihttpproxy.
+	CGI bool
+}
+
+// FromEnvironment returns a Config instance populated from the
+// environment variables HTTP_PROXY, HTTPS_PROXY and NO_PROXY (or the
+// lowercase versions thereof). HTTPS_PROXY takes precedence over
+// HTTP_PROXY for https requests.
+//
+// The environment values may be either a complete URL or a
+// "host[:port]", in which case the "http" scheme is assumed. An error
+// is returned if the value is a different form.
+func FromEnvironment() *Config {
+	return &Config{
+		HTTPProxy:  getEnvAny("HTTP_PROXY", "http_proxy"),
+		HTTPSProxy: getEnvAny("HTTPS_PROXY", "https_proxy"),
+		NoProxy:    getEnvAny("NO_PROXY", "no_proxy"),
+		CGI:        os.Getenv("REQUEST_METHOD") != "",
+	}
+}
+
+func getEnvAny(names ...string) string {
+	for _, n := range names {
+		if val := os.Getenv(n); val != "" {
+			return val
+		}
+	}
+	return ""
+}
+
+// ProxyFunc returns a function that determines the proxy URL to use for
+// a given request URL. Changing the contents of cfg will not affect
+// proxy functions created earlier.
+//
+// A nil URL and nil error are returned if no proxy is defined in the
+// environment, or a proxy should not be used for the given request, as
+// defined by NO_PROXY.
+//
+// As a special case, if req.URL.Host is "localhost" (with or without a
+// port number), then a nil URL and nil error will be returned.
+func (cfg *Config) ProxyFunc() func(reqURL *url.URL) (*url.URL, error) {
+	// Prevent Config changes from affecting the function calculation.
+	// TODO Preprocess proxy settings for more efficient evaluation.
+	cfg1 := *cfg
+	return cfg1.proxyForURL
+}
+
+func (cfg *Config) proxyForURL(reqURL *url.URL) (*url.URL, error) {
+	var proxy string
+	if reqURL.Scheme == "https" {
+		proxy = cfg.HTTPSProxy
+	}
+	if proxy == "" {
+		proxy = cfg.HTTPProxy
+		if proxy != "" && cfg.CGI {
+			return nil, errors.New("refusing to use HTTP_PROXY value in CGI environment; see golang.org/s/cgihttpproxy")
+		}
+	}
+	if proxy == "" {
+		return nil, nil
+	}
+	if !cfg.useProxy(canonicalAddr(reqURL)) {
+		return nil, nil
+	}
+	proxyURL, err := url.Parse(proxy)
+	if err != nil ||
+		(proxyURL.Scheme != "http" &&
+			proxyURL.Scheme != "https" &&
+			proxyURL.Scheme != "socks5") {
+		// proxy was bogus. Try prepending "http://" to it and
+		// see if that parses correctly. If not, we fall
+		// through and complain about the original one.
+		if proxyURL, err := url.Parse("http://" + proxy); err == nil {
+			return proxyURL, nil
+		}
+	}
+	if err != nil {
+		return nil, fmt.Errorf("invalid proxy address %q: %v", proxy, err)
+	}
+	return proxyURL, nil
+}
+
+// useProxy reports whether requests to addr should use a proxy,
+// according to the NO_PROXY or no_proxy environment variable.
+// addr is always a canonicalAddr with a host and port.
+func (cfg *Config) useProxy(addr string) bool {
+	if len(addr) == 0 {
+		return true
+	}
+	host, _, err := net.SplitHostPort(addr)
+	if err != nil {
+		return false
+	}
+	if host == "localhost" {
+		return false
+	}
+	if ip := net.ParseIP(host); ip != nil {
+		if ip.IsLoopback() {
+			return false
+		}
+	}
+
+	noProxy := cfg.NoProxy
+	if noProxy == "*" {
+		return false
+	}
+
+	addr = strings.ToLower(strings.TrimSpace(addr))
+	if hasPort(addr) {
+		addr = addr[:strings.LastIndex(addr, ":")]
+	}
+
+	for _, p := range strings.Split(noProxy, ",") {
+		p = strings.ToLower(strings.TrimSpace(p))
+		if len(p) == 0 {
+			continue
+		}
+		if hasPort(p) {
+			p = p[:strings.LastIndex(p, ":")]
+		}
+		if addr == p {
+			return false
+		}
+		if len(p) == 0 {
+			// There is no host part, likely the entry is malformed; ignore.
+			continue
+		}
+		if p[0] == '.' && (strings.HasSuffix(addr, p) || addr == p[1:]) {
+			// no_proxy ".foo.com" matches "bar.foo.com" or "foo.com"
+			return false
+		}
+		if p[0] != '.' && strings.HasSuffix(addr, p) && addr[len(addr)-len(p)-1] == '.' {
+			// no_proxy "foo.com" matches "bar.foo.com"
+			return false
+		}
+	}
+	return true
+}
+
+var portMap = map[string]string{
+	"http":   "80",
+	"https":  "443",
+	"socks5": "1080",
+}
+
+// canonicalAddr returns url.Host but always with a ":port" suffix
+func canonicalAddr(url *url.URL) string {
+	addr := url.Hostname()
+	if v, err := idnaASCII(addr); err == nil {
+		addr = v
+	}
+	port := url.Port()
+	if port == "" {
+		port = portMap[url.Scheme]
+	}
+	return net.JoinHostPort(addr, port)
+}
+
+// Given a string of the form "host", "host:port", or "[ipv6::address]:port",
+// return true if the string includes a port.
+func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }
+
+func idnaASCII(v string) (string, error) {
+	// TODO: Consider removing this check after verifying performance is okay.
+	// Right now punycode verification, length checks, context checks, and the
+	// permissible character tests are all omitted. It also prevents the ToASCII
+	// call from salvaging an invalid IDN, when possible. As a result it may be
+	// possible to have two IDNs that appear identical to the user where the
+	// ASCII-only version causes an error downstream whereas the non-ASCII
+	// version does not.
+	// Note that for correct ASCII IDNs ToASCII will only do considerably more
+	// work, but it will not cause an allocation.
+	if isASCII(v) {
+		return v, nil
+	}
+	return idna.Lookup.ToASCII(v)
+}
+
+func isASCII(s string) bool {
+	for i := 0; i < len(s); i++ {
+		if s[i] >= utf8.RuneSelf {
+			return false
+		}
+	}
+	return true
+}

+ 301 - 0
vendor/golang.org/x/net/http/httpproxy/proxy_test.go

@@ -0,0 +1,301 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package httpproxy_test
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"net/url"
+	"os"
+	"strings"
+	"testing"
+
+	"golang.org/x/net/http/httpproxy"
+)
+
+// setHelper calls t.Helper() for Go 1.9+ (see go19_test.go) and does nothing otherwise.
+var setHelper = func(t *testing.T) {}
+
+type proxyForURLTest struct {
+	cfg     httpproxy.Config
+	req     string // URL to fetch; blank means "http://example.com"
+	want    string
+	wanterr error
+}
+
+func (t proxyForURLTest) String() string {
+	var buf bytes.Buffer
+	space := func() {
+		if buf.Len() > 0 {
+			buf.WriteByte(' ')
+		}
+	}
+	if t.cfg.HTTPProxy != "" {
+		fmt.Fprintf(&buf, "http_proxy=%q", t.cfg.HTTPProxy)
+	}
+	if t.cfg.HTTPSProxy != "" {
+		space()
+		fmt.Fprintf(&buf, "https_proxy=%q", t.cfg.HTTPSProxy)
+	}
+	if t.cfg.NoProxy != "" {
+		space()
+		fmt.Fprintf(&buf, "no_proxy=%q", t.cfg.NoProxy)
+	}
+	req := "http://example.com"
+	if t.req != "" {
+		req = t.req
+	}
+	space()
+	fmt.Fprintf(&buf, "req=%q", req)
+	return strings.TrimSpace(buf.String())
+}
+
+var proxyForURLTests = []proxyForURLTest{{
+	cfg: httpproxy.Config{
+		HTTPProxy: "127.0.0.1:8080",
+	},
+	want: "http://127.0.0.1:8080",
+}, {
+	cfg: httpproxy.Config{
+		HTTPProxy: "cache.corp.example.com:1234",
+	},
+	want: "http://cache.corp.example.com:1234",
+}, {
+	cfg: httpproxy.Config{
+		HTTPProxy: "cache.corp.example.com",
+	},
+	want: "http://cache.corp.example.com",
+}, {
+	cfg: httpproxy.Config{
+		HTTPProxy: "https://cache.corp.example.com",
+	},
+	want: "https://cache.corp.example.com",
+}, {
+	cfg: httpproxy.Config{
+		HTTPProxy: "http://127.0.0.1:8080",
+	},
+	want: "http://127.0.0.1:8080",
+}, {
+	cfg: httpproxy.Config{
+		HTTPProxy: "https://127.0.0.1:8080",
+	},
+	want: "https://127.0.0.1:8080",
+}, {
+	cfg: httpproxy.Config{
+		HTTPProxy: "socks5://127.0.0.1",
+	},
+	want: "socks5://127.0.0.1",
+}, {
+	// Don't use secure for http
+	cfg: httpproxy.Config{
+		HTTPProxy:  "http.proxy.tld",
+		HTTPSProxy: "secure.proxy.tld",
+	},
+	req:  "http://insecure.tld/",
+	want: "http://http.proxy.tld",
+}, {
+	// Use secure for https.
+	cfg: httpproxy.Config{
+		HTTPProxy:  "http.proxy.tld",
+		HTTPSProxy: "secure.proxy.tld",
+	},
+	req:  "https://secure.tld/",
+	want: "http://secure.proxy.tld",
+}, {
+	cfg: httpproxy.Config{
+		HTTPProxy:  "http.proxy.tld",
+		HTTPSProxy: "https://secure.proxy.tld",
+	},
+	req:  "https://secure.tld/",
+	want: "https://secure.proxy.tld",
+}, {
+	// Issue 16405: don't use HTTP_PROXY in a CGI environment,
+	// where HTTP_PROXY can be attacker-controlled.
+	cfg: httpproxy.Config{
+		HTTPProxy: "http://10.1.2.3:8080",
+		CGI:       true,
+	},
+	want:    "<nil>",
+	wanterr: errors.New("refusing to use HTTP_PROXY value in CGI environment; see golang.org/s/cgihttpproxy"),
+}, {
+	// HTTPS proxy is still used even in CGI environment.
+	// (perhaps dubious but it's the historical behaviour).
+	cfg: httpproxy.Config{
+		HTTPSProxy: "https://secure.proxy.tld",
+		CGI:        true,
+	},
+	req:  "https://secure.tld/",
+	want: "https://secure.proxy.tld",
+}, {
+	want: "<nil>",
+}, {
+	cfg: httpproxy.Config{
+		NoProxy:   "example.com",
+		HTTPProxy: "proxy",
+	},
+	req:  "http://example.com/",
+	want: "<nil>",
+}, {
+	cfg: httpproxy.Config{
+		NoProxy:   ".example.com",
+		HTTPProxy: "proxy",
+	},
+	req:  "http://example.com/",
+	want: "<nil>",
+}, {
+	cfg: httpproxy.Config{
+		NoProxy:   "ample.com",
+		HTTPProxy: "proxy",
+	},
+	req:  "http://example.com/",
+	want: "http://proxy",
+}, {
+	cfg: httpproxy.Config{
+		NoProxy:   "example.com",
+		HTTPProxy: "proxy",
+	},
+	req:  "http://foo.example.com/",
+	want: "<nil>",
+}, {
+	cfg: httpproxy.Config{
+		NoProxy:   ".foo.com",
+		HTTPProxy: "proxy",
+	},
+	req:  "http://example.com/",
+	want: "http://proxy",
+}}
+
+func testProxyForURL(t *testing.T, tt proxyForURLTest) {
+	setHelper(t)
+	reqURLStr := tt.req
+	if reqURLStr == "" {
+		reqURLStr = "http://example.com"
+	}
+	reqURL, err := url.Parse(reqURLStr)
+	if err != nil {
+		t.Errorf("invalid URL %q", reqURLStr)
+		return
+	}
+	cfg := tt.cfg
+	proxyForURL := cfg.ProxyFunc()
+	url, err := proxyForURL(reqURL)
+	if g, e := fmt.Sprintf("%v", err), fmt.Sprintf("%v", tt.wanterr); g != e {
+		t.Errorf("%v: got error = %q, want %q", tt, g, e)
+		return
+	}
+	if got := fmt.Sprintf("%s", url); got != tt.want {
+		t.Errorf("%v: got URL = %q, want %q", tt, url, tt.want)
+	}
+
+	// Check that changing the Config doesn't change the results
+	// of the functuon.
+	cfg = httpproxy.Config{}
+	url, err = proxyForURL(reqURL)
+	if g, e := fmt.Sprintf("%v", err), fmt.Sprintf("%v", tt.wanterr); g != e {
+		t.Errorf("(after mutating config) %v: got error = %q, want %q", tt, g, e)
+		return
+	}
+	if got := fmt.Sprintf("%s", url); got != tt.want {
+		t.Errorf("(after mutating config) %v: got URL = %q, want %q", tt, url, tt.want)
+	}
+}
+
+func TestProxyForURL(t *testing.T) {
+	for _, tt := range proxyForURLTests {
+		testProxyForURL(t, tt)
+	}
+}
+
+func TestFromEnvironment(t *testing.T) {
+	os.Setenv("HTTP_PROXY", "httpproxy")
+	os.Setenv("HTTPS_PROXY", "httpsproxy")
+	os.Setenv("NO_PROXY", "noproxy")
+	os.Setenv("REQUEST_METHOD", "")
+	got := httpproxy.FromEnvironment()
+	want := httpproxy.Config{
+		HTTPProxy:  "httpproxy",
+		HTTPSProxy: "httpsproxy",
+		NoProxy:    "noproxy",
+	}
+	if *got != want {
+		t.Errorf("unexpected proxy config, got %#v want %#v", got, want)
+	}
+}
+
+func TestFromEnvironmentWithRequestMethod(t *testing.T) {
+	os.Setenv("HTTP_PROXY", "httpproxy")
+	os.Setenv("HTTPS_PROXY", "httpsproxy")
+	os.Setenv("NO_PROXY", "noproxy")
+	os.Setenv("REQUEST_METHOD", "PUT")
+	got := httpproxy.FromEnvironment()
+	want := httpproxy.Config{
+		HTTPProxy:  "httpproxy",
+		HTTPSProxy: "httpsproxy",
+		NoProxy:    "noproxy",
+		CGI:        true,
+	}
+	if *got != want {
+		t.Errorf("unexpected proxy config, got %#v want %#v", got, want)
+	}
+}
+
+func TestFromEnvironmentLowerCase(t *testing.T) {
+	os.Setenv("http_proxy", "httpproxy")
+	os.Setenv("https_proxy", "httpsproxy")
+	os.Setenv("no_proxy", "noproxy")
+	os.Setenv("REQUEST_METHOD", "")
+	got := httpproxy.FromEnvironment()
+	want := httpproxy.Config{
+		HTTPProxy:  "httpproxy",
+		HTTPSProxy: "httpsproxy",
+		NoProxy:    "noproxy",
+	}
+	if *got != want {
+		t.Errorf("unexpected proxy config, got %#v want %#v", got, want)
+	}
+}
+
+var UseProxyTests = []struct {
+	host  string
+	match bool
+}{
+	// Never proxy localhost:
+	{"localhost", false},
+	{"127.0.0.1", false},
+	{"127.0.0.2", false},
+	{"[::1]", false},
+	{"[::2]", true}, // not a loopback address
+
+	{"barbaz.net", false},     // match as .barbaz.net
+	{"foobar.com", false},     // have a port but match
+	{"foofoobar.com", true},   // not match as a part of foobar.com
+	{"baz.com", true},         // not match as a part of barbaz.com
+	{"localhost.net", true},   // not match as suffix of address
+	{"local.localhost", true}, // not match as prefix as address
+	{"barbarbaz.net", true},   // not match because NO_PROXY have a '.'
+	{"www.foobar.com", false}, // match because NO_PROXY includes "foobar.com"
+}
+
+func TestUseProxy(t *testing.T) {
+	cfg := &httpproxy.Config{
+		NoProxy: "foobar.com, .barbaz.net",
+	}
+	for _, test := range UseProxyTests {
+		if httpproxy.ExportUseProxy(cfg, test.host+":80") != test.match {
+			t.Errorf("useProxy(%v) = %v, want %v", test.host, !test.match, test.match)
+		}
+	}
+}
+
+func TestInvalidNoProxy(t *testing.T) {
+	cfg := &httpproxy.Config{
+		NoProxy: ":1",
+	}
+	ok := httpproxy.ExportUseProxy(cfg, "example.com:80") // should not panic
+	if !ok {
+		t.Errorf("useProxy unexpected return; got false; want true")
+	}
+}

+ 1 - 1
vendor/golang.org/x/net/http2/ciphers.go

@@ -5,7 +5,7 @@
 package http2
 package http2
 
 
 // A list of the possible cipher suite ids. Taken from
 // A list of the possible cipher suite ids. Taken from
-// http://www.iana.org/assignments/tls-parameters/tls-parameters.txt
+// https://www.iana.org/assignments/tls-parameters/tls-parameters.txt
 
 
 const (
 const (
 	cipher_TLS_NULL_WITH_NULL_NULL               uint16 = 0x0000
 	cipher_TLS_NULL_WITH_NULL_NULL               uint16 = 0x0000

+ 1 - 1
vendor/golang.org/x/net/http2/ciphers_test.go

@@ -9,7 +9,7 @@ import "testing"
 func TestIsBadCipherBad(t *testing.T) {
 func TestIsBadCipherBad(t *testing.T) {
 	for _, c := range badCiphers {
 	for _, c := range badCiphers {
 		if !isBadCipher(c) {
 		if !isBadCipher(c) {
-			t.Errorf("Wrong result for isBadCipher(%d), want true")
+			t.Errorf("Wrong result for isBadCipher(%d), want true", c)
 		}
 		}
 	}
 	}
 }
 }

+ 1 - 1
vendor/golang.org/x/net/http2/configure_transport.go

@@ -73,7 +73,7 @@ type noDialH2RoundTripper struct{ t *Transport }
 
 
 func (rt noDialH2RoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
 func (rt noDialH2RoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
 	res, err := rt.t.RoundTrip(req)
 	res, err := rt.t.RoundTrip(req)
-	if err == ErrNoCachedConn {
+	if isNoCachedConnError(err) {
 		return nil, http.ErrSkipAltProtocol
 		return nil, http.ErrSkipAltProtocol
 	}
 	}
 	return res, err
 	return res, err

+ 8 - 5
vendor/golang.org/x/net/http2/errors.go

@@ -87,13 +87,16 @@ type goAwayFlowError struct{}
 
 
 func (goAwayFlowError) Error() string { return "connection exceeded flow control window size" }
 func (goAwayFlowError) Error() string { return "connection exceeded flow control window size" }
 
 
-// connErrorReason wraps a ConnectionError with an informative error about why it occurs.
-
+// connError represents an HTTP/2 ConnectionError error code, along
+// with a string (for debugging) explaining why.
+//
 // Errors of this type are only returned by the frame parser functions
 // Errors of this type are only returned by the frame parser functions
-// and converted into ConnectionError(ErrCodeProtocol).
+// and converted into ConnectionError(Code), after stashing away
+// the Reason into the Framer's errDetail field, accessible via
+// the (*Framer).ErrorDetail method.
 type connError struct {
 type connError struct {
-	Code   ErrCode
-	Reason string
+	Code   ErrCode // the ConnectionError error code
+	Reason string  // additional reason
 }
 }
 
 
 func (e connError) Error() string {
 func (e connError) Error() string {

+ 2 - 0
vendor/golang.org/x/net/http2/go18.go

@@ -52,3 +52,5 @@ func reqGetBody(req *http.Request) func() (io.ReadCloser, error) {
 func reqBodyIsNoBody(body io.ReadCloser) bool {
 func reqBodyIsNoBody(body io.ReadCloser) bool {
 	return body == http.NoBody
 	return body == http.NoBody
 }
 }
+
+func go18httpNoBody() io.ReadCloser { return http.NoBody } // for tests only

+ 0 - 1
vendor/golang.org/x/net/http2/go19_test.go

@@ -46,7 +46,6 @@ func TestServerGracefulShutdown(t *testing.T) {
 	wanth := [][2]string{
 	wanth := [][2]string{
 		{":status", "200"},
 		{":status", "200"},
 		{"x-foo", "bar"},
 		{"x-foo", "bar"},
-		{"content-type", "text/plain; charset=utf-8"},
 		{"content-length", "0"},
 		{"content-length", "0"},
 	}
 	}
 	if !reflect.DeepEqual(goth, wanth) {
 	if !reflect.DeepEqual(goth, wanth) {

+ 1 - 0
vendor/golang.org/x/net/http2/h2demo/.gitignore

@@ -3,3 +3,4 @@ h2demo.linux
 client-id.dat
 client-id.dat
 client-secret.dat
 client-secret.dat
 token.dat
 token.dat
+ca-certificates.crt

+ 11 - 0
vendor/golang.org/x/net/http2/h2demo/Dockerfile

@@ -0,0 +1,11 @@
+# Copyright 2018 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+FROM scratch
+LABEL maintainer "golang-dev@googlegroups.com"
+
+COPY ca-certificates.crt /etc/ssl/certs/
+COPY h2demo /
+ENTRYPOINT ["/h2demo", "-prod"]
+

+ 134 - 0
vendor/golang.org/x/net/http2/h2demo/Dockerfile.0

@@ -0,0 +1,134 @@
+# Copyright 2018 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+FROM golang:1.9
+LABEL maintainer "golang-dev@googlegroups.com"
+
+ENV CGO_ENABLED=0
+
+# BEGIN deps (run `make update-deps` to update)
+
+# Repo cloud.google.com/go at 1d0c2da (2018-01-30)
+ENV REV=1d0c2da40456a9b47f5376165f275424acc15c09
+RUN go get -d cloud.google.com/go/compute/metadata `#and 6 other pkgs` &&\
+    (cd /go/src/cloud.google.com/go && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
+
+# Repo github.com/golang/protobuf at 9255415 (2018-01-25)
+ENV REV=925541529c1fa6821df4e44ce2723319eb2be768
+RUN go get -d github.com/golang/protobuf/proto `#and 6 other pkgs` &&\
+    (cd /go/src/github.com/golang/protobuf && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
+
+# Repo github.com/googleapis/gax-go at 317e000 (2017-09-15)
+ENV REV=317e0006254c44a0ac427cc52a0e083ff0b9622f
+RUN go get -d github.com/googleapis/gax-go &&\
+    (cd /go/src/github.com/googleapis/gax-go && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
+
+# Repo go4.org at 034d17a (2017-05-25)
+ENV REV=034d17a462f7b2dcd1a4a73553ec5357ff6e6c6e
+RUN go get -d go4.org/syncutil/singleflight &&\
+    (cd /go/src/go4.org && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
+
+# Repo golang.org/x/build at 8aa9ee0 (2018-02-01)
+ENV REV=8aa9ee0e557fd49c14113e5ba106e13a5b455460
+RUN go get -d golang.org/x/build/autocertcache &&\
+    (cd /go/src/golang.org/x/build && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
+
+# Repo golang.org/x/crypto at 1875d0a (2018-01-27)
+ENV REV=1875d0a70c90e57f11972aefd42276df65e895b9
+RUN go get -d golang.org/x/crypto/acme `#and 2 other pkgs` &&\
+    (cd /go/src/golang.org/x/crypto && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
+
+# Repo golang.org/x/oauth2 at 30785a2 (2018-01-04)
+ENV REV=30785a2c434e431ef7c507b54617d6a951d5f2b4
+RUN go get -d golang.org/x/oauth2 `#and 5 other pkgs` &&\
+    (cd /go/src/golang.org/x/oauth2 && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
+
+# Repo golang.org/x/text at e19ae14 (2017-12-27)
+ENV REV=e19ae1496984b1c655b8044a65c0300a3c878dd3
+RUN go get -d golang.org/x/text/secure/bidirule `#and 4 other pkgs` &&\
+    (cd /go/src/golang.org/x/text && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
+
+# Repo google.golang.org/api at 7d0e2d3 (2018-01-30)
+ENV REV=7d0e2d350555821bef5a5b8aecf0d12cc1def633
+RUN go get -d google.golang.org/api/gensupport `#and 9 other pkgs` &&\
+    (cd /go/src/google.golang.org/api && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
+
+# Repo google.golang.org/genproto at 4eb30f4 (2018-01-25)
+ENV REV=4eb30f4778eed4c258ba66527a0d4f9ec8a36c45
+RUN go get -d google.golang.org/genproto/googleapis/api/annotations `#and 3 other pkgs` &&\
+    (cd /go/src/google.golang.org/genproto && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
+
+# Repo google.golang.org/grpc at 0bd008f (2018-01-25)
+ENV REV=0bd008f5fadb62d228f12b18d016709e8139a7af
+RUN go get -d google.golang.org/grpc `#and 23 other pkgs` &&\
+    (cd /go/src/google.golang.org/grpc && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
+
+# Optimization to speed up iterative development, not necessary for correctness:
+RUN go install cloud.google.com/go/compute/metadata \
+	cloud.google.com/go/iam \
+	cloud.google.com/go/internal \
+	cloud.google.com/go/internal/optional \
+	cloud.google.com/go/internal/version \
+	cloud.google.com/go/storage \
+	github.com/golang/protobuf/proto \
+	github.com/golang/protobuf/protoc-gen-go/descriptor \
+	github.com/golang/protobuf/ptypes \
+	github.com/golang/protobuf/ptypes/any \
+	github.com/golang/protobuf/ptypes/duration \
+	github.com/golang/protobuf/ptypes/timestamp \
+	github.com/googleapis/gax-go \
+	go4.org/syncutil/singleflight \
+	golang.org/x/build/autocertcache \
+	golang.org/x/crypto/acme \
+	golang.org/x/crypto/acme/autocert \
+	golang.org/x/oauth2 \
+	golang.org/x/oauth2/google \
+	golang.org/x/oauth2/internal \
+	golang.org/x/oauth2/jws \
+	golang.org/x/oauth2/jwt \
+	golang.org/x/text/secure/bidirule \
+	golang.org/x/text/transform \
+	golang.org/x/text/unicode/bidi \
+	golang.org/x/text/unicode/norm \
+	google.golang.org/api/gensupport \
+	google.golang.org/api/googleapi \
+	google.golang.org/api/googleapi/internal/uritemplates \
+	google.golang.org/api/googleapi/transport \
+	google.golang.org/api/internal \
+	google.golang.org/api/iterator \
+	google.golang.org/api/option \
+	google.golang.org/api/storage/v1 \
+	google.golang.org/api/transport/http \
+	google.golang.org/genproto/googleapis/api/annotations \
+	google.golang.org/genproto/googleapis/iam/v1 \
+	google.golang.org/genproto/googleapis/rpc/status \
+	google.golang.org/grpc \
+	google.golang.org/grpc/balancer \
+	google.golang.org/grpc/balancer/base \
+	google.golang.org/grpc/balancer/roundrobin \
+	google.golang.org/grpc/codes \
+	google.golang.org/grpc/connectivity \
+	google.golang.org/grpc/credentials \
+	google.golang.org/grpc/encoding \
+	google.golang.org/grpc/encoding/proto \
+	google.golang.org/grpc/grpclb/grpc_lb_v1/messages \
+	google.golang.org/grpc/grpclog \
+	google.golang.org/grpc/internal \
+	google.golang.org/grpc/keepalive \
+	google.golang.org/grpc/metadata \
+	google.golang.org/grpc/naming \
+	google.golang.org/grpc/peer \
+	google.golang.org/grpc/resolver \
+	google.golang.org/grpc/resolver/dns \
+	google.golang.org/grpc/resolver/passthrough \
+	google.golang.org/grpc/stats \
+	google.golang.org/grpc/status \
+	google.golang.org/grpc/tap \
+	google.golang.org/grpc/transport
+# END deps
+
+COPY . /go/src/golang.org/x/net/
+
+RUN go install -tags "h2demo netgo" -ldflags "-linkmode=external -extldflags '-static -pthread'" golang.org/x/net/http2/h2demo
+

+ 53 - 6
vendor/golang.org/x/net/http2/h2demo/Makefile

@@ -1,8 +1,55 @@
-h2demo.linux: h2demo.go
-	GOOS=linux go build --tags=h2demo -o h2demo.linux .
+# Copyright 2018 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
 
 
-FORCE:
+MUTABLE_VERSION ?= latest
+VERSION ?= $(shell git rev-parse --short HEAD)
+
+IMAGE_STAGING := gcr.io/go-dashboard-dev/h2demo
+IMAGE_PROD := gcr.io/symbolic-datum-552/h2demo
+
+DOCKER_IMAGE_build0=build0/h2demo:latest
+DOCKER_CTR_build0=h2demo-build0
+
+build0: *.go Dockerfile.0
+	docker build --force-rm -f Dockerfile.0 --tag=$(DOCKER_IMAGE_build0) ../..
+
+h2demo: build0
+	docker create --name $(DOCKER_CTR_build0) $(DOCKER_IMAGE_build0)
+	docker cp $(DOCKER_CTR_build0):/go/bin/$@ $@
+	docker rm $(DOCKER_CTR_build0)
+
+ca-certificates.crt:
+	docker create --name $(DOCKER_CTR_build0) $(DOCKER_IMAGE_build0)
+	docker cp $(DOCKER_CTR_build0):/etc/ssl/certs/$@ $@
+	docker rm $(DOCKER_CTR_build0)
 
 
-upload: FORCE
-	go install golang.org/x/build/cmd/upload
-	upload --verbose --osarch=linux-amd64 --tags=h2demo --file=go:golang.org/x/net/http2/h2demo --public http2-demo-server-tls/h2demo
+update-deps:
+	go install golang.org/x/build/cmd/gitlock
+	gitlock --update=Dockerfile.0 --ignore=golang.org/x/net --tags=h2demo golang.org/x/net/http2/h2demo
+
+docker-prod: Dockerfile h2demo ca-certificates.crt
+	docker build --force-rm --tag=$(IMAGE_PROD):$(VERSION) .
+	docker tag $(IMAGE_PROD):$(VERSION) $(IMAGE_PROD):$(MUTABLE_VERSION)
+docker-staging: Dockerfile h2demo ca-certificates.crt
+	docker build --force-rm --tag=$(IMAGE_STAGING):$(VERSION) .
+	docker tag $(IMAGE_STAGING):$(VERSION) $(IMAGE_STAGING):$(MUTABLE_VERSION)
+
+push-prod: docker-prod
+	gcloud docker -- push $(IMAGE_PROD):$(MUTABLE_VERSION)
+	gcloud docker -- push $(IMAGE_PROD):$(VERSION)
+push-staging: docker-staging
+	gcloud docker -- push $(IMAGE_STAGING):$(MUTABLE_VERSION)
+	gcloud docker -- push $(IMAGE_STAGING):$(VERSION)
+
+deploy-prod: push-prod
+	kubectl set image deployment/h2demo-deployment h2demo=$(IMAGE_PROD):$(VERSION)
+deploy-staging: push-staging
+	kubectl set image deployment/h2demo-deployment h2demo=$(IMAGE_STAGING):$(VERSION)
+
+.PHONY: clean
+clean:
+	$(RM) h2demo
+	$(RM) ca-certificates.crt
+
+FORCE:

+ 28 - 0
vendor/golang.org/x/net/http2/h2demo/deployment-prod.yaml

@@ -0,0 +1,28 @@
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+  name: h2demo-deployment
+spec:
+  replicas: 1
+  template:
+    metadata:
+      labels:
+        app: h2demo
+      annotations:
+        container.seccomp.security.alpha.kubernetes.io/h2demo: docker/default
+        container.apparmor.security.beta.kubernetes.io/h2demo: runtime/default
+    spec:
+      containers:
+      - name: h2demo
+        image: gcr.io/symbolic-datum-552/h2demo:latest
+        imagePullPolicy: Always
+        command: ["/h2demo", "-prod"]
+        ports:
+        - containerPort: 80
+        - containerPort: 443
+        resources:
+          requests:
+            cpu: "1"
+            memory: "1Gi"
+          limits:
+            memory: "2Gi"

+ 19 - 14
vendor/golang.org/x/net/http2/h2demo/h2demo.go

@@ -8,6 +8,7 @@ package main
 
 
 import (
 import (
 	"bytes"
 	"bytes"
+	"context"
 	"crypto/tls"
 	"crypto/tls"
 	"flag"
 	"flag"
 	"fmt"
 	"fmt"
@@ -19,7 +20,6 @@ import (
 	"log"
 	"log"
 	"net"
 	"net"
 	"net/http"
 	"net/http"
-	"os"
 	"path"
 	"path"
 	"regexp"
 	"regexp"
 	"runtime"
 	"runtime"
@@ -28,7 +28,9 @@ import (
 	"sync"
 	"sync"
 	"time"
 	"time"
 
 
+	"cloud.google.com/go/storage"
 	"go4.org/syncutil/singleflight"
 	"go4.org/syncutil/singleflight"
+	"golang.org/x/build/autocertcache"
 	"golang.org/x/crypto/acme/autocert"
 	"golang.org/x/crypto/acme/autocert"
 	"golang.org/x/net/http2"
 	"golang.org/x/net/http2"
 )
 )
@@ -426,19 +428,10 @@ func httpHost() string {
 	}
 	}
 }
 }
 
 
-func serveProdTLS() error {
-	const cacheDir = "/var/cache/autocert"
-	if err := os.MkdirAll(cacheDir, 0700); err != nil {
-		return err
-	}
-	m := autocert.Manager{
-		Cache:      autocert.DirCache(cacheDir),
-		Prompt:     autocert.AcceptTOS,
-		HostPolicy: autocert.HostWhitelist("http2.golang.org"),
-	}
+func serveProdTLS(autocertManager *autocert.Manager) error {
 	srv := &http.Server{
 	srv := &http.Server{
 		TLSConfig: &tls.Config{
 		TLSConfig: &tls.Config{
-			GetCertificate: m.GetCertificate,
+			GetCertificate: autocertManager.GetCertificate,
 		},
 		},
 	}
 	}
 	http2.ConfigureServer(srv, &http2.Server{
 	http2.ConfigureServer(srv, &http2.Server{
@@ -468,9 +461,21 @@ func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
 }
 }
 
 
 func serveProd() error {
 func serveProd() error {
+	log.Printf("running in production mode")
+
+	storageClient, err := storage.NewClient(context.Background())
+	if err != nil {
+		log.Fatalf("storage.NewClient: %v", err)
+	}
+	autocertManager := &autocert.Manager{
+		Prompt:     autocert.AcceptTOS,
+		HostPolicy: autocert.HostWhitelist("http2.golang.org"),
+		Cache:      autocertcache.NewGoogleCloudStorageCache(storageClient, "golang-h2demo-autocert"),
+	}
+
 	errc := make(chan error, 2)
 	errc := make(chan error, 2)
-	go func() { errc <- http.ListenAndServe(":80", nil) }()
-	go func() { errc <- serveProdTLS() }()
+	go func() { errc <- http.ListenAndServe(":80", autocertManager.HTTPHandler(http.DefaultServeMux)) }()
+	go func() { errc <- serveProdTLS(autocertManager) }()
 	return <-errc
 	return <-errc
 }
 }
 
 

+ 17 - 0
vendor/golang.org/x/net/http2/h2demo/service.yaml

@@ -0,0 +1,17 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: h2demo
+spec:
+  externalTrafficPolicy: Local
+  ports:
+    - port: 80
+      targetPort: 80
+      name: http
+    - port: 443
+      targetPort: 443
+      name: https
+  selector:
+    app: h2demo
+  type: LoadBalancer
+  loadBalancerIP: 130.211.116.44

+ 15 - 2
vendor/golang.org/x/net/http2/h2i/h2i.go

@@ -45,6 +45,7 @@ var (
 	flagNextProto = flag.String("nextproto", "h2,h2-14", "Comma-separated list of NPN/ALPN protocol names to negotiate.")
 	flagNextProto = flag.String("nextproto", "h2,h2-14", "Comma-separated list of NPN/ALPN protocol names to negotiate.")
 	flagInsecure  = flag.Bool("insecure", false, "Whether to skip TLS cert validation")
 	flagInsecure  = flag.Bool("insecure", false, "Whether to skip TLS cert validation")
 	flagSettings  = flag.String("settings", "empty", "comma-separated list of KEY=value settings for the initial SETTINGS frame. The magic value 'empty' sends an empty initial settings frame, and the magic value 'omit' causes no initial settings frame to be sent.")
 	flagSettings  = flag.String("settings", "empty", "comma-separated list of KEY=value settings for the initial SETTINGS frame. The magic value 'empty' sends an empty initial settings frame, and the magic value 'omit' causes no initial settings frame to be sent.")
+	flagDial      = flag.String("dial", "", "optional ip:port to dial, to connect to a host:port but use a different SNI name (including a SNI name without DNS)")
 )
 )
 
 
 type command struct {
 type command struct {
@@ -147,11 +148,14 @@ func (app *h2i) Main() error {
 		InsecureSkipVerify: *flagInsecure,
 		InsecureSkipVerify: *flagInsecure,
 	}
 	}
 
 
-	hostAndPort := withPort(app.host)
+	hostAndPort := *flagDial
+	if hostAndPort == "" {
+		hostAndPort = withPort(app.host)
+	}
 	log.Printf("Connecting to %s ...", hostAndPort)
 	log.Printf("Connecting to %s ...", hostAndPort)
 	tc, err := tls.Dial("tcp", hostAndPort, cfg)
 	tc, err := tls.Dial("tcp", hostAndPort, cfg)
 	if err != nil {
 	if err != nil {
-		return fmt.Errorf("Error dialing %s: %v", withPort(app.host), err)
+		return fmt.Errorf("Error dialing %s: %v", hostAndPort, err)
 	}
 	}
 	log.Printf("Connected to %v", tc.RemoteAddr())
 	log.Printf("Connected to %v", tc.RemoteAddr())
 	defer tc.Close()
 	defer tc.Close()
@@ -460,6 +464,15 @@ func (app *h2i) readFrames() error {
 				app.hdec = hpack.NewDecoder(tableSize, app.onNewHeaderField)
 				app.hdec = hpack.NewDecoder(tableSize, app.onNewHeaderField)
 			}
 			}
 			app.hdec.Write(f.HeaderBlockFragment())
 			app.hdec.Write(f.HeaderBlockFragment())
+		case *http2.PushPromiseFrame:
+			if app.hdec == nil {
+				// TODO: if the user uses h2i to send a SETTINGS frame advertising
+				// something larger, we'll need to respect SETTINGS_HEADER_TABLE_SIZE
+				// and stuff here instead of using the 4k default. But for now:
+				tableSize := uint32(4 << 10)
+				app.hdec = hpack.NewDecoder(tableSize, app.onNewHeaderField)
+			}
+			app.hdec.Write(f.HeaderBlockFragment())
 		}
 		}
 	}
 	}
 }
 }

+ 1 - 1
vendor/golang.org/x/net/http2/hpack/encode.go

@@ -206,7 +206,7 @@ func appendVarInt(dst []byte, n byte, i uint64) []byte {
 }
 }
 
 
 // appendHpackString appends s, as encoded in "String Literal"
 // appendHpackString appends s, as encoded in "String Literal"
-// representation, to dst and returns the the extended buffer.
+// representation, to dst and returns the extended buffer.
 //
 //
 // s will be encoded in Huffman codes only when it produces strictly
 // s will be encoded in Huffman codes only when it produces strictly
 // shorter byte string.
 // shorter byte string.

+ 7 - 3
vendor/golang.org/x/net/http2/http2.go

@@ -312,7 +312,7 @@ func mustUint31(v int32) uint32 {
 }
 }
 
 
 // bodyAllowedForStatus reports whether a given response status code
 // bodyAllowedForStatus reports whether a given response status code
-// permits a body. See RFC 2616, section 4.4.
+// permits a body. See RFC 7230, section 3.3.
 func bodyAllowedForStatus(status int) bool {
 func bodyAllowedForStatus(status int) bool {
 	switch {
 	switch {
 	case status >= 100 && status <= 199:
 	case status >= 100 && status <= 199:
@@ -376,12 +376,16 @@ func (s *sorter) SortStrings(ss []string) {
 // validPseudoPath reports whether v is a valid :path pseudo-header
 // validPseudoPath reports whether v is a valid :path pseudo-header
 // value. It must be either:
 // value. It must be either:
 //
 //
-//     *) a non-empty string starting with '/', but not with with "//",
+//     *) a non-empty string starting with '/'
 //     *) the string '*', for OPTIONS requests.
 //     *) the string '*', for OPTIONS requests.
 //
 //
 // For now this is only used a quick check for deciding when to clean
 // For now this is only used a quick check for deciding when to clean
 // up Opaque URLs before sending requests from the Transport.
 // up Opaque URLs before sending requests from the Transport.
 // See golang.org/issue/16847
 // See golang.org/issue/16847
+//
+// We used to enforce that the path also didn't start with "//", but
+// Google's GFE accepts such paths and Chrome sends them, so ignore
+// that part of the spec. See golang.org/issue/19103.
 func validPseudoPath(v string) bool {
 func validPseudoPath(v string) bool {
-	return (len(v) > 0 && v[0] == '/' && (len(v) == 1 || v[1] != '/')) || v == "*"
+	return (len(v) > 0 && v[0] == '/') || v == "*"
 }
 }

+ 2 - 0
vendor/golang.org/x/net/http2/not_go18.go

@@ -25,3 +25,5 @@ func reqGetBody(req *http.Request) func() (io.ReadCloser, error) {
 }
 }
 
 
 func reqBodyIsNoBody(io.ReadCloser) bool { return false }
 func reqBodyIsNoBody(io.ReadCloser) bool { return false }
+
+func go18httpNoBody() io.ReadCloser { return nil } // for tests only

+ 91 - 71
vendor/golang.org/x/net/http2/server.go

@@ -46,6 +46,7 @@ import (
 	"sync"
 	"sync"
 	"time"
 	"time"
 
 
+	"golang.org/x/net/http/httpguts"
 	"golang.org/x/net/http2/hpack"
 	"golang.org/x/net/http2/hpack"
 )
 )
 
 
@@ -220,12 +221,15 @@ func ConfigureServer(s *http.Server, conf *Server) error {
 	} else if s.TLSConfig.CipherSuites != nil {
 	} else if s.TLSConfig.CipherSuites != nil {
 		// If they already provided a CipherSuite list, return
 		// If they already provided a CipherSuite list, return
 		// an error if it has a bad order or is missing
 		// an error if it has a bad order or is missing
-		// ECDHE_RSA_WITH_AES_128_GCM_SHA256.
-		const requiredCipher = tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
+		// ECDHE_RSA_WITH_AES_128_GCM_SHA256 or ECDHE_ECDSA_WITH_AES_128_GCM_SHA256.
 		haveRequired := false
 		haveRequired := false
 		sawBad := false
 		sawBad := false
 		for i, cs := range s.TLSConfig.CipherSuites {
 		for i, cs := range s.TLSConfig.CipherSuites {
-			if cs == requiredCipher {
+			switch cs {
+			case tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+				// Alternative MTI cipher to not discourage ECDSA-only servers.
+				// See http://golang.org/cl/30721 for further information.
+				tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
 				haveRequired = true
 				haveRequired = true
 			}
 			}
 			if isBadCipher(cs) {
 			if isBadCipher(cs) {
@@ -235,7 +239,7 @@ func ConfigureServer(s *http.Server, conf *Server) error {
 			}
 			}
 		}
 		}
 		if !haveRequired {
 		if !haveRequired {
-			return fmt.Errorf("http2: TLSConfig.CipherSuites is missing HTTP/2-required TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256")
+			return fmt.Errorf("http2: TLSConfig.CipherSuites is missing an HTTP/2-required AES_128_GCM_SHA256 cipher.")
 		}
 		}
 	}
 	}
 
 
@@ -403,7 +407,7 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
 			// addresses during development.
 			// addresses during development.
 			//
 			//
 			// TODO: optionally enforce? Or enforce at the time we receive
 			// TODO: optionally enforce? Or enforce at the time we receive
-			// a new request, and verify the the ServerName matches the :authority?
+			// a new request, and verify the ServerName matches the :authority?
 			// But that precludes proxy situations, perhaps.
 			// But that precludes proxy situations, perhaps.
 			//
 			//
 			// So for now, do nothing here again.
 			// So for now, do nothing here again.
@@ -649,7 +653,7 @@ func (sc *serverConn) condlogf(err error, format string, args ...interface{}) {
 	if err == nil {
 	if err == nil {
 		return
 		return
 	}
 	}
-	if err == io.EOF || err == io.ErrUnexpectedEOF || isClosedConnError(err) {
+	if err == io.EOF || err == io.ErrUnexpectedEOF || isClosedConnError(err) || err == errPrefaceTimeout {
 		// Boring, expected errors.
 		// Boring, expected errors.
 		sc.vlogf(format, args...)
 		sc.vlogf(format, args...)
 	} else {
 	} else {
@@ -853,8 +857,13 @@ func (sc *serverConn) serve() {
 			}
 			}
 		}
 		}
 
 
-		if sc.inGoAway && sc.curOpenStreams() == 0 && !sc.needToSendGoAway && !sc.writingFrame {
-			return
+		// Start the shutdown timer after sending a GOAWAY. When sending GOAWAY
+		// with no error code (graceful shutdown), don't start the timer until
+		// all open streams have been completed.
+		sentGoAway := sc.inGoAway && !sc.needToSendGoAway && !sc.writingFrame
+		gracefulShutdownComplete := sc.goAwayCode == ErrCodeNo && sc.curOpenStreams() == 0
+		if sentGoAway && sc.shutdownTimer == nil && (sc.goAwayCode != ErrCodeNo || gracefulShutdownComplete) {
+			sc.shutDownIn(goAwayTimeout)
 		}
 		}
 	}
 	}
 }
 }
@@ -889,8 +898,11 @@ func (sc *serverConn) sendServeMsg(msg interface{}) {
 	}
 	}
 }
 }
 
 
-// readPreface reads the ClientPreface greeting from the peer
-// or returns an error on timeout or an invalid greeting.
+var errPrefaceTimeout = errors.New("timeout waiting for client preface")
+
+// readPreface reads the ClientPreface greeting from the peer or
+// returns errPrefaceTimeout on timeout, or an error if the greeting
+// is invalid.
 func (sc *serverConn) readPreface() error {
 func (sc *serverConn) readPreface() error {
 	errc := make(chan error, 1)
 	errc := make(chan error, 1)
 	go func() {
 	go func() {
@@ -908,7 +920,7 @@ func (sc *serverConn) readPreface() error {
 	defer timer.Stop()
 	defer timer.Stop()
 	select {
 	select {
 	case <-timer.C:
 	case <-timer.C:
-		return errors.New("timeout waiting for client preface")
+		return errPrefaceTimeout
 	case err := <-errc:
 	case err := <-errc:
 		if err == nil {
 		if err == nil {
 			if VerboseLogs {
 			if VerboseLogs {
@@ -1218,30 +1230,31 @@ func (sc *serverConn) startGracefulShutdown() {
 	sc.shutdownOnce.Do(func() { sc.sendServeMsg(gracefulShutdownMsg) })
 	sc.shutdownOnce.Do(func() { sc.sendServeMsg(gracefulShutdownMsg) })
 }
 }
 
 
+// After sending GOAWAY, the connection will close after goAwayTimeout.
+// If we close the connection immediately after sending GOAWAY, there may
+// be unsent data in our kernel receive buffer, which will cause the kernel
+// to send a TCP RST on close() instead of a FIN. This RST will abort the
+// connection immediately, whether or not the client had received the GOAWAY.
+//
+// Ideally we should delay for at least 1 RTT + epsilon so the client has
+// a chance to read the GOAWAY and stop sending messages. Measuring RTT
+// is hard, so we approximate with 1 second. See golang.org/issue/18701.
+//
+// This is a var so it can be shorter in tests, where all requests uses the
+// loopback interface making the expected RTT very small.
+//
+// TODO: configurable?
+var goAwayTimeout = 1 * time.Second
+
 func (sc *serverConn) startGracefulShutdownInternal() {
 func (sc *serverConn) startGracefulShutdownInternal() {
-	sc.goAwayIn(ErrCodeNo, 0)
+	sc.goAway(ErrCodeNo)
 }
 }
 
 
 func (sc *serverConn) goAway(code ErrCode) {
 func (sc *serverConn) goAway(code ErrCode) {
-	sc.serveG.check()
-	var forceCloseIn time.Duration
-	if code != ErrCodeNo {
-		forceCloseIn = 250 * time.Millisecond
-	} else {
-		// TODO: configurable
-		forceCloseIn = 1 * time.Second
-	}
-	sc.goAwayIn(code, forceCloseIn)
-}
-
-func (sc *serverConn) goAwayIn(code ErrCode, forceCloseIn time.Duration) {
 	sc.serveG.check()
 	sc.serveG.check()
 	if sc.inGoAway {
 	if sc.inGoAway {
 		return
 		return
 	}
 	}
-	if forceCloseIn != 0 {
-		sc.shutDownIn(forceCloseIn)
-	}
 	sc.inGoAway = true
 	sc.inGoAway = true
 	sc.needToSendGoAway = true
 	sc.needToSendGoAway = true
 	sc.goAwayCode = code
 	sc.goAwayCode = code
@@ -1805,7 +1818,7 @@ func (st *stream) processTrailerHeaders(f *MetaHeadersFrame) error {
 	if st.trailer != nil {
 	if st.trailer != nil {
 		for _, hf := range f.RegularFields() {
 		for _, hf := range f.RegularFields() {
 			key := sc.canonicalHeader(hf.Name)
 			key := sc.canonicalHeader(hf.Name)
-			if !ValidTrailerHeader(key) {
+			if !httpguts.ValidTrailerHeader(key) {
 				// TODO: send more details to the peer somehow. But http2 has
 				// TODO: send more details to the peer somehow. But http2 has
 				// no way to send debug data at a stream level. Discuss with
 				// no way to send debug data at a stream level. Discuss with
 				// HTTP folk.
 				// HTTP folk.
@@ -2252,6 +2265,7 @@ type responseWriterState struct {
 	wroteHeader   bool        // WriteHeader called (explicitly or implicitly). Not necessarily sent to user yet.
 	wroteHeader   bool        // WriteHeader called (explicitly or implicitly). Not necessarily sent to user yet.
 	sentHeader    bool        // have we sent the header frame?
 	sentHeader    bool        // have we sent the header frame?
 	handlerDone   bool        // handler has finished
 	handlerDone   bool        // handler has finished
+	dirty         bool        // a Write failed; don't reuse this responseWriterState
 
 
 	sentContentLen int64 // non-zero if handler set a Content-Length header
 	sentContentLen int64 // non-zero if handler set a Content-Length header
 	wroteBytes     int64
 	wroteBytes     int64
@@ -2271,8 +2285,8 @@ func (rws *responseWriterState) hasTrailers() bool { return len(rws.trailers) !=
 // written in the trailers at the end of the response.
 // written in the trailers at the end of the response.
 func (rws *responseWriterState) declareTrailer(k string) {
 func (rws *responseWriterState) declareTrailer(k string) {
 	k = http.CanonicalHeaderKey(k)
 	k = http.CanonicalHeaderKey(k)
-	if !ValidTrailerHeader(k) {
-		// Forbidden by RFC 2616 14.40.
+	if !httpguts.ValidTrailerHeader(k) {
+		// Forbidden by RFC 7230, section 4.1.2.
 		rws.conn.logf("ignoring invalid trailer %q", k)
 		rws.conn.logf("ignoring invalid trailer %q", k)
 		return
 		return
 	}
 	}
@@ -2309,8 +2323,16 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
 			clen = strconv.Itoa(len(p))
 			clen = strconv.Itoa(len(p))
 		}
 		}
 		_, hasContentType := rws.snapHeader["Content-Type"]
 		_, hasContentType := rws.snapHeader["Content-Type"]
-		if !hasContentType && bodyAllowedForStatus(rws.status) {
-			ctype = http.DetectContentType(p)
+		if !hasContentType && bodyAllowedForStatus(rws.status) && len(p) > 0 {
+			if cto := rws.snapHeader.Get("X-Content-Type-Options"); strings.EqualFold("nosniff", cto) {
+				// nosniff is an explicit directive not to guess a content-type.
+				// Content-sniffing is no less susceptible to polyglot attacks via
+				// hosted content when done on the server.
+				ctype = "application/octet-stream"
+				rws.conn.logf("http2: WriteHeader called with X-Content-Type-Options:nosniff but no Content-Type")
+			} else {
+				ctype = http.DetectContentType(p)
+			}
 		}
 		}
 		var date string
 		var date string
 		if _, ok := rws.snapHeader["Date"]; !ok {
 		if _, ok := rws.snapHeader["Date"]; !ok {
@@ -2333,6 +2355,7 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
 			date:          date,
 			date:          date,
 		})
 		})
 		if err != nil {
 		if err != nil {
+			rws.dirty = true
 			return 0, err
 			return 0, err
 		}
 		}
 		if endStream {
 		if endStream {
@@ -2354,6 +2377,7 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
 	if len(p) > 0 || endStream {
 	if len(p) > 0 || endStream {
 		// only send a 0 byte DATA frame if we're ending the stream.
 		// only send a 0 byte DATA frame if we're ending the stream.
 		if err := rws.conn.writeDataFromHandler(rws.stream, p, endStream); err != nil {
 		if err := rws.conn.writeDataFromHandler(rws.stream, p, endStream); err != nil {
+			rws.dirty = true
 			return 0, err
 			return 0, err
 		}
 		}
 	}
 	}
@@ -2365,6 +2389,9 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
 			trailers:  rws.trailers,
 			trailers:  rws.trailers,
 			endStream: true,
 			endStream: true,
 		})
 		})
+		if err != nil {
+			rws.dirty = true
+		}
 		return len(p), err
 		return len(p), err
 	}
 	}
 	return len(p), nil
 	return len(p), nil
@@ -2388,7 +2415,7 @@ const TrailerPrefix = "Trailer:"
 // after the header has already been flushed. Because the Go
 // after the header has already been flushed. Because the Go
 // ResponseWriter interface has no way to set Trailers (only the
 // ResponseWriter interface has no way to set Trailers (only the
 // Header), and because we didn't want to expand the ResponseWriter
 // Header), and because we didn't want to expand the ResponseWriter
-// interface, and because nobody used trailers, and because RFC 2616
+// interface, and because nobody used trailers, and because RFC 7230
 // says you SHOULD (but not must) predeclare any trailers in the
 // says you SHOULD (but not must) predeclare any trailers in the
 // header, the official ResponseWriter rules said trailers in Go must
 // header, the official ResponseWriter rules said trailers in Go must
 // be predeclared, and then we reuse the same ResponseWriter.Header()
 // be predeclared, and then we reuse the same ResponseWriter.Header()
@@ -2472,6 +2499,24 @@ func (w *responseWriter) Header() http.Header {
 	return rws.handlerHeader
 	return rws.handlerHeader
 }
 }
 
 
+// checkWriteHeaderCode is a copy of net/http's checkWriteHeaderCode.
+func checkWriteHeaderCode(code int) {
+	// Issue 22880: require valid WriteHeader status codes.
+	// For now we only enforce that it's three digits.
+	// In the future we might block things over 599 (600 and above aren't defined
+	// at http://httpwg.org/specs/rfc7231.html#status.codes)
+	// and we might block under 200 (once we have more mature 1xx support).
+	// But for now any three digits.
+	//
+	// We used to send "HTTP/1.1 000 0" on the wire in responses but there's
+	// no equivalent bogus thing we can realistically send in HTTP/2,
+	// so we'll consistently panic instead and help people find their bugs
+	// early. (We can't return an error from WriteHeader even if we wanted to.)
+	if code < 100 || code > 999 {
+		panic(fmt.Sprintf("invalid WriteHeader code %v", code))
+	}
+}
+
 func (w *responseWriter) WriteHeader(code int) {
 func (w *responseWriter) WriteHeader(code int) {
 	rws := w.rws
 	rws := w.rws
 	if rws == nil {
 	if rws == nil {
@@ -2482,6 +2527,7 @@ func (w *responseWriter) WriteHeader(code int) {
 
 
 func (rws *responseWriterState) writeHeader(code int) {
 func (rws *responseWriterState) writeHeader(code int) {
 	if !rws.wroteHeader {
 	if !rws.wroteHeader {
+		checkWriteHeaderCode(code)
 		rws.wroteHeader = true
 		rws.wroteHeader = true
 		rws.status = code
 		rws.status = code
 		if len(rws.handlerHeader) > 0 {
 		if len(rws.handlerHeader) > 0 {
@@ -2504,7 +2550,7 @@ func cloneHeader(h http.Header) http.Header {
 //
 //
 // * Handler calls w.Write or w.WriteString ->
 // * Handler calls w.Write or w.WriteString ->
 // * -> rws.bw (*bufio.Writer) ->
 // * -> rws.bw (*bufio.Writer) ->
-// * (Handler migth call Flush)
+// * (Handler might call Flush)
 // * -> chunkWriter{rws}
 // * -> chunkWriter{rws}
 // * -> responseWriterState.writeChunk(p []byte)
 // * -> responseWriterState.writeChunk(p []byte)
 // * -> responseWriterState.writeChunk (most of the magic; see comment there)
 // * -> responseWriterState.writeChunk (most of the magic; see comment there)
@@ -2543,10 +2589,19 @@ func (w *responseWriter) write(lenData int, dataB []byte, dataS string) (n int,
 
 
 func (w *responseWriter) handlerDone() {
 func (w *responseWriter) handlerDone() {
 	rws := w.rws
 	rws := w.rws
+	dirty := rws.dirty
 	rws.handlerDone = true
 	rws.handlerDone = true
 	w.Flush()
 	w.Flush()
 	w.rws = nil
 	w.rws = nil
-	responseWriterStatePool.Put(rws)
+	if !dirty {
+		// Only recycle the pool if all prior Write calls to
+		// the serverConn goroutine completed successfully. If
+		// they returned earlier due to resets from the peer
+		// there might still be write goroutines outstanding
+		// from the serverConn referencing the rws memory. See
+		// issue 20704.
+		responseWriterStatePool.Put(rws)
+	}
 }
 }
 
 
 // Push errors.
 // Push errors.
@@ -2744,7 +2799,7 @@ func (sc *serverConn) startPush(msg *startPushRequest) {
 }
 }
 
 
 // foreachHeaderElement splits v according to the "#rule" construction
 // foreachHeaderElement splits v according to the "#rule" construction
-// in RFC 2616 section 2.1 and calls fn for each non-empty element.
+// in RFC 7230 section 7 and calls fn for each non-empty element.
 func foreachHeaderElement(v string, fn func(string)) {
 func foreachHeaderElement(v string, fn func(string)) {
 	v = textproto.TrimString(v)
 	v = textproto.TrimString(v)
 	if v == "" {
 	if v == "" {
@@ -2792,41 +2847,6 @@ func new400Handler(err error) http.HandlerFunc {
 	}
 	}
 }
 }
 
 
-// ValidTrailerHeader reports whether name is a valid header field name to appear
-// in trailers.
-// See: http://tools.ietf.org/html/rfc7230#section-4.1.2
-func ValidTrailerHeader(name string) bool {
-	name = http.CanonicalHeaderKey(name)
-	if strings.HasPrefix(name, "If-") || badTrailer[name] {
-		return false
-	}
-	return true
-}
-
-var badTrailer = map[string]bool{
-	"Authorization":       true,
-	"Cache-Control":       true,
-	"Connection":          true,
-	"Content-Encoding":    true,
-	"Content-Length":      true,
-	"Content-Range":       true,
-	"Content-Type":        true,
-	"Expect":              true,
-	"Host":                true,
-	"Keep-Alive":          true,
-	"Max-Forwards":        true,
-	"Pragma":              true,
-	"Proxy-Authenticate":  true,
-	"Proxy-Authorization": true,
-	"Proxy-Connection":    true,
-	"Range":               true,
-	"Realm":               true,
-	"Te":                  true,
-	"Trailer":             true,
-	"Transfer-Encoding":   true,
-	"Www-Authenticate":    true,
-}
-
 // h1ServerKeepAlivesDisabled reports whether hs has its keep-alives
 // h1ServerKeepAlivesDisabled reports whether hs has its keep-alives
 // disabled. See comments on h1ServerShutdownChan above for why
 // disabled. See comments on h1ServerShutdownChan above for why
 // the code is written this way.
 // the code is written this way.

+ 86 - 12
vendor/golang.org/x/net/http2/server_test.go

@@ -68,6 +68,7 @@ type serverTester struct {
 
 
 func init() {
 func init() {
 	testHookOnPanicMu = new(sync.Mutex)
 	testHookOnPanicMu = new(sync.Mutex)
+	goAwayTimeout = 25 * time.Millisecond
 }
 }
 
 
 func resetHooks() {
 func resetHooks() {
@@ -286,7 +287,7 @@ func (st *serverTester) greetAndCheckSettings(checkSetting func(s Setting) error
 
 
 		case *WindowUpdateFrame:
 		case *WindowUpdateFrame:
 			if f.FrameHeader.StreamID != 0 {
 			if f.FrameHeader.StreamID != 0 {
-				st.t.Fatalf("WindowUpdate StreamID = %d; want 0", f.FrameHeader.StreamID, 0)
+				st.t.Fatalf("WindowUpdate StreamID = %d; want 0", f.FrameHeader.StreamID)
 			}
 			}
 			incr := uint32((&Server{}).initialConnRecvWindowSize() - initialWindowSize)
 			incr := uint32((&Server{}).initialConnRecvWindowSize() - initialWindowSize)
 			if f.Increment != incr {
 			if f.Increment != incr {
@@ -1717,7 +1718,6 @@ func TestServer_Response_NoData_Header_FooBar(t *testing.T) {
 		wanth := [][2]string{
 		wanth := [][2]string{
 			{":status", "200"},
 			{":status", "200"},
 			{"foo-bar", "some-value"},
 			{"foo-bar", "some-value"},
-			{"content-type", "text/plain; charset=utf-8"},
 			{"content-length", "0"},
 			{"content-length", "0"},
 		}
 		}
 		if !reflect.DeepEqual(goth, wanth) {
 		if !reflect.DeepEqual(goth, wanth) {
@@ -1760,6 +1760,42 @@ func TestServer_Response_Data_Sniff_DoesntOverride(t *testing.T) {
 	})
 	})
 }
 }
 
 
+func TestServer_Response_Nosniff_WithoutContentType(t *testing.T) {
+	const msg = "<html>this is HTML."
+	testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error {
+		w.Header().Set("X-Content-Type-Options", "nosniff")
+		w.WriteHeader(200)
+		io.WriteString(w, msg)
+		return nil
+	}, func(st *serverTester) {
+		getSlash(st)
+		hf := st.wantHeaders()
+		if hf.StreamEnded() {
+			t.Fatal("don't want END_STREAM, expecting data")
+		}
+		if !hf.HeadersEnded() {
+			t.Fatal("want END_HEADERS flag")
+		}
+		goth := st.decodeHeader(hf.HeaderBlockFragment())
+		wanth := [][2]string{
+			{":status", "200"},
+			{"x-content-type-options", "nosniff"},
+			{"content-type", "application/octet-stream"},
+			{"content-length", strconv.Itoa(len(msg))},
+		}
+		if !reflect.DeepEqual(goth, wanth) {
+			t.Errorf("Got headers %v; want %v", goth, wanth)
+		}
+		df := st.wantData()
+		if !df.StreamEnded() {
+			t.Error("expected DATA to have END_STREAM flag")
+		}
+		if got := string(df.Data()); got != msg {
+			t.Errorf("got DATA %q; want %q", got, msg)
+		}
+	})
+}
+
 func TestServer_Response_TransferEncoding_chunked(t *testing.T) {
 func TestServer_Response_TransferEncoding_chunked(t *testing.T) {
 	const msg = "hi"
 	const msg = "hi"
 	testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error {
 	testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error {
@@ -2877,9 +2913,9 @@ func testServerWritesTrailers(t *testing.T, withFlush bool) {
 		w.Header().Set("Trailer:post-header-trailer2", "hi2")
 		w.Header().Set("Trailer:post-header-trailer2", "hi2")
 		w.Header().Set("Trailer:Range", "invalid")
 		w.Header().Set("Trailer:Range", "invalid")
 		w.Header().Set("Trailer:Foo\x01Bogus", "invalid")
 		w.Header().Set("Trailer:Foo\x01Bogus", "invalid")
-		w.Header().Set("Transfer-Encoding", "should not be included; Forbidden by RFC 2616 14.40")
-		w.Header().Set("Content-Length", "should not be included; Forbidden by RFC 2616 14.40")
-		w.Header().Set("Trailer", "should not be included; Forbidden by RFC 2616 14.40")
+		w.Header().Set("Transfer-Encoding", "should not be included; Forbidden by RFC 7230 4.1.2")
+		w.Header().Set("Content-Length", "should not be included; Forbidden by RFC 7230 4.1.2")
+		w.Header().Set("Trailer", "should not be included; Forbidden by RFC 7230 4.1.2")
 		return nil
 		return nil
 	}, func(st *serverTester) {
 	}, func(st *serverTester) {
 		getSlash(st)
 		getSlash(st)
@@ -2952,7 +2988,6 @@ func TestServerDoesntWriteInvalidHeaders(t *testing.T) {
 		wanth := [][2]string{
 		wanth := [][2]string{
 			{":status", "200"},
 			{":status", "200"},
 			{"ok1", "x"},
 			{"ok1", "x"},
-			{"content-type", "text/plain; charset=utf-8"},
 			{"content-length", "0"},
 			{"content-length", "0"},
 		}
 		}
 		if !reflect.DeepEqual(goth, wanth) {
 		if !reflect.DeepEqual(goth, wanth) {
@@ -2972,7 +3007,7 @@ func BenchmarkServerGets(b *testing.B) {
 	defer st.Close()
 	defer st.Close()
 	st.greet()
 	st.greet()
 
 
-	// Give the server quota to reply. (plus it has the the 64KB)
+	// Give the server quota to reply. (plus it has the 64KB)
 	if err := st.fr.WriteWindowUpdate(0, uint32(b.N*len(msg))); err != nil {
 	if err := st.fr.WriteWindowUpdate(0, uint32(b.N*len(msg))); err != nil {
 		b.Fatal(err)
 		b.Fatal(err)
 	}
 	}
@@ -3010,7 +3045,7 @@ func BenchmarkServerPosts(b *testing.B) {
 	defer st.Close()
 	defer st.Close()
 	st.greet()
 	st.greet()
 
 
-	// Give the server quota to reply. (plus it has the the 64KB)
+	// Give the server quota to reply. (plus it has the 64KB)
 	if err := st.fr.WriteWindowUpdate(0, uint32(b.N*len(msg))); err != nil {
 	if err := st.fr.WriteWindowUpdate(0, uint32(b.N*len(msg))); err != nil {
 		b.Fatal(err)
 		b.Fatal(err)
 	}
 	}
@@ -3188,12 +3223,18 @@ func TestConfigureServer(t *testing.T) {
 				CipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
 				CipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
 			},
 			},
 		},
 		},
+		{
+			name: "just the alternative required cipher suite",
+			tlsConfig: &tls.Config{
+				CipherSuites: []uint16{tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
+			},
+		},
 		{
 		{
 			name: "missing required cipher suite",
 			name: "missing required cipher suite",
 			tlsConfig: &tls.Config{
 			tlsConfig: &tls.Config{
 				CipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384},
 				CipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384},
 			},
 			},
-			wantErr: "is missing HTTP/2-required TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
+			wantErr: "is missing an HTTP/2-required AES_128_GCM_SHA256 cipher.",
 		},
 		},
 		{
 		{
 			name: "required after bad",
 			name: "required after bad",
@@ -3259,7 +3300,6 @@ func TestServerNoAutoContentLengthOnHead(t *testing.T) {
 	headers := st.decodeHeader(h.HeaderBlockFragment())
 	headers := st.decodeHeader(h.HeaderBlockFragment())
 	want := [][2]string{
 	want := [][2]string{
 		{":status", "200"},
 		{":status", "200"},
-		{"content-type", "text/plain; charset=utf-8"},
 	}
 	}
 	if !reflect.DeepEqual(headers, want) {
 	if !reflect.DeepEqual(headers, want) {
 		t.Errorf("Headers mismatch.\n got: %q\nwant: %q\n", headers, want)
 		t.Errorf("Headers mismatch.\n got: %q\nwant: %q\n", headers, want)
@@ -3312,7 +3352,7 @@ func BenchmarkServer_GetRequest(b *testing.B) {
 	defer st.Close()
 	defer st.Close()
 
 
 	st.greet()
 	st.greet()
-	// Give the server quota to reply. (plus it has the the 64KB)
+	// Give the server quota to reply. (plus it has the 64KB)
 	if err := st.fr.WriteWindowUpdate(0, uint32(b.N*len(msg))); err != nil {
 	if err := st.fr.WriteWindowUpdate(0, uint32(b.N*len(msg))); err != nil {
 		b.Fatal(err)
 		b.Fatal(err)
 	}
 	}
@@ -3343,7 +3383,7 @@ func BenchmarkServer_PostRequest(b *testing.B) {
 	})
 	})
 	defer st.Close()
 	defer st.Close()
 	st.greet()
 	st.greet()
-	// Give the server quota to reply. (plus it has the the 64KB)
+	// Give the server quota to reply. (plus it has the 64KB)
 	if err := st.fr.WriteWindowUpdate(0, uint32(b.N*len(msg))); err != nil {
 	if err := st.fr.WriteWindowUpdate(0, uint32(b.N*len(msg))); err != nil {
 		b.Fatal(err)
 		b.Fatal(err)
 	}
 	}
@@ -3685,3 +3725,37 @@ func TestRequestBodyReadCloseRace(t *testing.T) {
 		<-done
 		<-done
 	}
 	}
 }
 }
+
+func TestIssue20704Race(t *testing.T) {
+	if testing.Short() && os.Getenv("GO_BUILDER_NAME") == "" {
+		t.Skip("skipping in short mode")
+	}
+	const (
+		itemSize  = 1 << 10
+		itemCount = 100
+	)
+
+	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+		for i := 0; i < itemCount; i++ {
+			_, err := w.Write(make([]byte, itemSize))
+			if err != nil {
+				return
+			}
+		}
+	}, optOnlyServer)
+	defer st.Close()
+
+	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
+	defer tr.CloseIdleConnections()
+	cl := &http.Client{Transport: tr}
+
+	for i := 0; i < 1000; i++ {
+		resp, err := cl.Get(st.ts.URL)
+		if err != nil {
+			t.Fatal(err)
+		}
+		// Force a RST stream to the server by closing without
+		// reading the body:
+		resp.Body.Close()
+	}
+}

+ 361 - 178
vendor/golang.org/x/net/http2/transport.go

@@ -18,6 +18,7 @@ import (
 	"io/ioutil"
 	"io/ioutil"
 	"log"
 	"log"
 	"math"
 	"math"
+	mathrand "math/rand"
 	"net"
 	"net"
 	"net/http"
 	"net/http"
 	"sort"
 	"sort"
@@ -86,7 +87,7 @@ type Transport struct {
 
 
 	// MaxHeaderListSize is the http2 SETTINGS_MAX_HEADER_LIST_SIZE to
 	// MaxHeaderListSize is the http2 SETTINGS_MAX_HEADER_LIST_SIZE to
 	// send in the initial settings frame. It is how many bytes
 	// send in the initial settings frame. It is how many bytes
-	// of response headers are allow. Unlike the http2 spec, zero here
+	// of response headers are allowed. Unlike the http2 spec, zero here
 	// means to use a default limit (currently 10MB). If you actually
 	// means to use a default limit (currently 10MB). If you actually
 	// want to advertise an ulimited value to the peer, Transport
 	// want to advertise an ulimited value to the peer, Transport
 	// interprets the highest possible value here (0xffffffff or 1<<32-1)
 	// interprets the highest possible value here (0xffffffff or 1<<32-1)
@@ -164,15 +165,17 @@ type ClientConn struct {
 	goAwayDebug     string                   // goAway frame's debug data, retained as a string
 	goAwayDebug     string                   // goAway frame's debug data, retained as a string
 	streams         map[uint32]*clientStream // client-initiated
 	streams         map[uint32]*clientStream // client-initiated
 	nextStreamID    uint32
 	nextStreamID    uint32
+	pendingRequests int                       // requests blocked and waiting to be sent because len(streams) == maxConcurrentStreams
 	pings           map[[8]byte]chan struct{} // in flight ping data to notification channel
 	pings           map[[8]byte]chan struct{} // in flight ping data to notification channel
 	bw              *bufio.Writer
 	bw              *bufio.Writer
 	br              *bufio.Reader
 	br              *bufio.Reader
 	fr              *Framer
 	fr              *Framer
 	lastActive      time.Time
 	lastActive      time.Time
 	// Settings from peer: (also guarded by mu)
 	// Settings from peer: (also guarded by mu)
-	maxFrameSize         uint32
-	maxConcurrentStreams uint32
-	initialWindowSize    uint32
+	maxFrameSize          uint32
+	maxConcurrentStreams  uint32
+	peerMaxHeaderListSize uint64
+	initialWindowSize     uint32
 
 
 	hbuf    bytes.Buffer // HPACK encoder writes into this
 	hbuf    bytes.Buffer // HPACK encoder writes into this
 	henc    *hpack.Encoder
 	henc    *hpack.Encoder
@@ -216,35 +219,45 @@ type clientStream struct {
 	resTrailer *http.Header // client's Response.Trailer
 	resTrailer *http.Header // client's Response.Trailer
 }
 }
 
 
-// awaitRequestCancel runs in its own goroutine and waits for the user
-// to cancel a RoundTrip request, its context to expire, or for the
-// request to be done (any way it might be removed from the cc.streams
-// map: peer reset, successful completion, TCP connection breakage,
-// etc)
-func (cs *clientStream) awaitRequestCancel(req *http.Request) {
+// awaitRequestCancel waits for the user to cancel a request or for the done
+// channel to be signaled. A non-nil error is returned only if the request was
+// canceled.
+func awaitRequestCancel(req *http.Request, done <-chan struct{}) error {
 	ctx := reqContext(req)
 	ctx := reqContext(req)
 	if req.Cancel == nil && ctx.Done() == nil {
 	if req.Cancel == nil && ctx.Done() == nil {
-		return
+		return nil
 	}
 	}
 	select {
 	select {
 	case <-req.Cancel:
 	case <-req.Cancel:
-		cs.cancelStream()
-		cs.bufPipe.CloseWithError(errRequestCanceled)
+		return errRequestCanceled
 	case <-ctx.Done():
 	case <-ctx.Done():
+		return ctx.Err()
+	case <-done:
+		return nil
+	}
+}
+
+// awaitRequestCancel waits for the user to cancel a request, its context to
+// expire, or for the request to be done (any way it might be removed from the
+// cc.streams map: peer reset, successful completion, TCP connection breakage,
+// etc). If the request is canceled, then cs will be canceled and closed.
+func (cs *clientStream) awaitRequestCancel(req *http.Request) {
+	if err := awaitRequestCancel(req, cs.done); err != nil {
 		cs.cancelStream()
 		cs.cancelStream()
-		cs.bufPipe.CloseWithError(ctx.Err())
-	case <-cs.done:
+		cs.bufPipe.CloseWithError(err)
 	}
 	}
 }
 }
 
 
 func (cs *clientStream) cancelStream() {
 func (cs *clientStream) cancelStream() {
-	cs.cc.mu.Lock()
+	cc := cs.cc
+	cc.mu.Lock()
 	didReset := cs.didReset
 	didReset := cs.didReset
 	cs.didReset = true
 	cs.didReset = true
-	cs.cc.mu.Unlock()
+	cc.mu.Unlock()
 
 
 	if !didReset {
 	if !didReset {
-		cs.cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
+		cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
+		cc.forgetStreamID(cs.ID)
 	}
 	}
 }
 }
 
 
@@ -261,6 +274,13 @@ func (cs *clientStream) checkResetOrDone() error {
 	}
 	}
 }
 }
 
 
+func (cs *clientStream) getStartedWrite() bool {
+	cc := cs.cc
+	cc.mu.Lock()
+	defer cc.mu.Unlock()
+	return cs.startedWrite
+}
+
 func (cs *clientStream) abortRequestBodyWrite(err error) {
 func (cs *clientStream) abortRequestBodyWrite(err error) {
 	if err == nil {
 	if err == nil {
 		panic("nil error")
 		panic("nil error")
@@ -286,7 +306,26 @@ func (sew stickyErrWriter) Write(p []byte) (n int, err error) {
 	return
 	return
 }
 }
 
 
-var ErrNoCachedConn = errors.New("http2: no cached connection was available")
+// noCachedConnError is the concrete type of ErrNoCachedConn, which
+// needs to be detected by net/http regardless of whether it's its
+// bundled version (in h2_bundle.go with a rewritten type name) or
+// from a user's x/net/http2. As such, as it has a unique method name
+// (IsHTTP2NoCachedConnError) that net/http sniffs for via func
+// isNoCachedConnError.
+type noCachedConnError struct{}
+
+func (noCachedConnError) IsHTTP2NoCachedConnError() {}
+func (noCachedConnError) Error() string             { return "http2: no cached connection was available" }
+
+// isNoCachedConnError reports whether err is of type noCachedConnError
+// or its equivalent renamed type in net/http2's h2_bundle.go. Both types
+// may coexist in the same running program.
+func isNoCachedConnError(err error) bool {
+	_, ok := err.(interface{ IsHTTP2NoCachedConnError() })
+	return ok
+}
+
+var ErrNoCachedConn error = noCachedConnError{}
 
 
 // RoundTripOpt are options for the Transport.RoundTripOpt method.
 // RoundTripOpt are options for the Transport.RoundTripOpt method.
 type RoundTripOpt struct {
 type RoundTripOpt struct {
@@ -329,17 +368,28 @@ func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Res
 	}
 	}
 
 
 	addr := authorityAddr(req.URL.Scheme, req.URL.Host)
 	addr := authorityAddr(req.URL.Scheme, req.URL.Host)
-	for {
+	for retry := 0; ; retry++ {
 		cc, err := t.connPool().GetClientConn(req, addr)
 		cc, err := t.connPool().GetClientConn(req, addr)
 		if err != nil {
 		if err != nil {
 			t.vlogf("http2: Transport failed to get client conn for %s: %v", addr, err)
 			t.vlogf("http2: Transport failed to get client conn for %s: %v", addr, err)
 			return nil, err
 			return nil, err
 		}
 		}
 		traceGotConn(req, cc)
 		traceGotConn(req, cc)
-		res, err := cc.RoundTrip(req)
-		if err != nil {
-			if req, err = shouldRetryRequest(req, err); err == nil {
-				continue
+		res, gotErrAfterReqBodyWrite, err := cc.roundTrip(req)
+		if err != nil && retry <= 6 {
+			if req, err = shouldRetryRequest(req, err, gotErrAfterReqBodyWrite); err == nil {
+				// After the first retry, do exponential backoff with 10% jitter.
+				if retry == 0 {
+					continue
+				}
+				backoff := float64(uint(1) << (uint(retry) - 1))
+				backoff += backoff * (0.1 * mathrand.Float64())
+				select {
+				case <-time.After(time.Second * time.Duration(backoff)):
+					continue
+				case <-reqContext(req).Done():
+					return nil, reqContext(req).Err()
+				}
 			}
 			}
 		}
 		}
 		if err != nil {
 		if err != nil {
@@ -360,43 +410,50 @@ func (t *Transport) CloseIdleConnections() {
 }
 }
 
 
 var (
 var (
-	errClientConnClosed   = errors.New("http2: client conn is closed")
-	errClientConnUnusable = errors.New("http2: client conn not usable")
-
-	errClientConnGotGoAway                 = errors.New("http2: Transport received Server's graceful shutdown GOAWAY")
-	errClientConnGotGoAwayAfterSomeReqBody = errors.New("http2: Transport received Server's graceful shutdown GOAWAY; some request body already written")
+	errClientConnClosed    = errors.New("http2: client conn is closed")
+	errClientConnUnusable  = errors.New("http2: client conn not usable")
+	errClientConnGotGoAway = errors.New("http2: Transport received Server's graceful shutdown GOAWAY")
 )
 )
 
 
 // shouldRetryRequest is called by RoundTrip when a request fails to get
 // shouldRetryRequest is called by RoundTrip when a request fails to get
 // response headers. It is always called with a non-nil error.
 // response headers. It is always called with a non-nil error.
 // It returns either a request to retry (either the same request, or a
 // It returns either a request to retry (either the same request, or a
 // modified clone), or an error if the request can't be replayed.
 // modified clone), or an error if the request can't be replayed.
-func shouldRetryRequest(req *http.Request, err error) (*http.Request, error) {
-	switch err {
-	default:
+func shouldRetryRequest(req *http.Request, err error, afterBodyWrite bool) (*http.Request, error) {
+	if !canRetryError(err) {
 		return nil, err
 		return nil, err
-	case errClientConnUnusable, errClientConnGotGoAway:
+	}
+	if !afterBodyWrite {
 		return req, nil
 		return req, nil
-	case errClientConnGotGoAwayAfterSomeReqBody:
-		// If the Body is nil (or http.NoBody), it's safe to reuse
-		// this request and its Body.
-		if req.Body == nil || reqBodyIsNoBody(req.Body) {
-			return req, nil
-		}
-		// Otherwise we depend on the Request having its GetBody
-		// func defined.
-		getBody := reqGetBody(req) // Go 1.8: getBody = req.GetBody
-		if getBody == nil {
-			return nil, errors.New("http2: Transport: peer server initiated graceful shutdown after some of Request.Body was written; define Request.GetBody to avoid this error")
-		}
-		body, err := getBody()
-		if err != nil {
-			return nil, err
-		}
-		newReq := *req
-		newReq.Body = body
-		return &newReq, nil
 	}
 	}
+	// If the Body is nil (or http.NoBody), it's safe to reuse
+	// this request and its Body.
+	if req.Body == nil || reqBodyIsNoBody(req.Body) {
+		return req, nil
+	}
+	// Otherwise we depend on the Request having its GetBody
+	// func defined.
+	getBody := reqGetBody(req) // Go 1.8: getBody = req.GetBody
+	if getBody == nil {
+		return nil, fmt.Errorf("http2: Transport: cannot retry err [%v] after Request.Body was written; define Request.GetBody to avoid this error", err)
+	}
+	body, err := getBody()
+	if err != nil {
+		return nil, err
+	}
+	newReq := *req
+	newReq.Body = body
+	return &newReq, nil
+}
+
+func canRetryError(err error) bool {
+	if err == errClientConnUnusable || err == errClientConnGotGoAway {
+		return true
+	}
+	if se, ok := err.(StreamError); ok {
+		return se.Code == ErrCodeRefusedStream
+	}
+	return false
 }
 }
 
 
 func (t *Transport) dialClientConn(addr string, singleUse bool) (*ClientConn, error) {
 func (t *Transport) dialClientConn(addr string, singleUse bool) (*ClientConn, error) {
@@ -474,17 +531,18 @@ func (t *Transport) NewClientConn(c net.Conn) (*ClientConn, error) {
 
 
 func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, error) {
 func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, error) {
 	cc := &ClientConn{
 	cc := &ClientConn{
-		t:                    t,
-		tconn:                c,
-		readerDone:           make(chan struct{}),
-		nextStreamID:         1,
-		maxFrameSize:         16 << 10, // spec default
-		initialWindowSize:    65535,    // spec default
-		maxConcurrentStreams: 1000,     // "infinite", per spec. 1000 seems good enough.
-		streams:              make(map[uint32]*clientStream),
-		singleUse:            singleUse,
-		wantSettingsAck:      true,
-		pings:                make(map[[8]byte]chan struct{}),
+		t:                     t,
+		tconn:                 c,
+		readerDone:            make(chan struct{}),
+		nextStreamID:          1,
+		maxFrameSize:          16 << 10,           // spec default
+		initialWindowSize:     65535,              // spec default
+		maxConcurrentStreams:  1000,               // "infinite", per spec. 1000 seems good enough.
+		peerMaxHeaderListSize: 0xffffffffffffffff, // "infinite", per spec. Use 2^64-1 instead.
+		streams:               make(map[uint32]*clientStream),
+		singleUse:             singleUse,
+		wantSettingsAck:       true,
+		pings:                 make(map[[8]byte]chan struct{}),
 	}
 	}
 	if d := t.idleConnTimeout(); d != 0 {
 	if d := t.idleConnTimeout(); d != 0 {
 		cc.idleTimeout = d
 		cc.idleTimeout = d
@@ -560,6 +618,8 @@ func (cc *ClientConn) setGoAway(f *GoAwayFrame) {
 	}
 	}
 }
 }
 
 
+// CanTakeNewRequest reports whether the connection can take a new request,
+// meaning it has not been closed or received or sent a GOAWAY.
 func (cc *ClientConn) CanTakeNewRequest() bool {
 func (cc *ClientConn) CanTakeNewRequest() bool {
 	cc.mu.Lock()
 	cc.mu.Lock()
 	defer cc.mu.Unlock()
 	defer cc.mu.Unlock()
@@ -571,8 +631,7 @@ func (cc *ClientConn) canTakeNewRequestLocked() bool {
 		return false
 		return false
 	}
 	}
 	return cc.goAway == nil && !cc.closed &&
 	return cc.goAway == nil && !cc.closed &&
-		int64(len(cc.streams)+1) < int64(cc.maxConcurrentStreams) &&
-		cc.nextStreamID < math.MaxInt32
+		int64(cc.nextStreamID)+int64(cc.pendingRequests) < math.MaxInt32
 }
 }
 
 
 // onIdleTimeout is called from a time.AfterFunc goroutine. It will
 // onIdleTimeout is called from a time.AfterFunc goroutine. It will
@@ -694,7 +753,7 @@ func checkConnHeaders(req *http.Request) error {
 // req.ContentLength, where 0 actually means zero (not unknown) and -1
 // req.ContentLength, where 0 actually means zero (not unknown) and -1
 // means unknown.
 // means unknown.
 func actualContentLength(req *http.Request) int64 {
 func actualContentLength(req *http.Request) int64 {
-	if req.Body == nil {
+	if req.Body == nil || reqBodyIsNoBody(req.Body) {
 		return 0
 		return 0
 	}
 	}
 	if req.ContentLength != 0 {
 	if req.ContentLength != 0 {
@@ -704,8 +763,13 @@ func actualContentLength(req *http.Request) int64 {
 }
 }
 
 
 func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
 func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
+	resp, _, err := cc.roundTrip(req)
+	return resp, err
+}
+
+func (cc *ClientConn) roundTrip(req *http.Request) (res *http.Response, gotErrAfterReqBodyWrite bool, err error) {
 	if err := checkConnHeaders(req); err != nil {
 	if err := checkConnHeaders(req); err != nil {
-		return nil, err
+		return nil, false, err
 	}
 	}
 	if cc.idleTimer != nil {
 	if cc.idleTimer != nil {
 		cc.idleTimer.Stop()
 		cc.idleTimer.Stop()
@@ -713,20 +777,19 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
 
 
 	trailers, err := commaSeparatedTrailers(req)
 	trailers, err := commaSeparatedTrailers(req)
 	if err != nil {
 	if err != nil {
-		return nil, err
+		return nil, false, err
 	}
 	}
 	hasTrailers := trailers != ""
 	hasTrailers := trailers != ""
 
 
 	cc.mu.Lock()
 	cc.mu.Lock()
-	cc.lastActive = time.Now()
-	if cc.closed || !cc.canTakeNewRequestLocked() {
+	if err := cc.awaitOpenSlotForRequest(req); err != nil {
 		cc.mu.Unlock()
 		cc.mu.Unlock()
-		return nil, errClientConnUnusable
+		return nil, false, err
 	}
 	}
 
 
 	body := req.Body
 	body := req.Body
-	hasBody := body != nil
 	contentLen := actualContentLength(req)
 	contentLen := actualContentLength(req)
+	hasBody := contentLen != 0
 
 
 	// TODO(bradfitz): this is a copy of the logic in net/http. Unify somewhere?
 	// TODO(bradfitz): this is a copy of the logic in net/http. Unify somewhere?
 	var requestedGzip bool
 	var requestedGzip bool
@@ -755,7 +818,7 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
 	hdrs, err := cc.encodeHeaders(req, requestedGzip, trailers, contentLen)
 	hdrs, err := cc.encodeHeaders(req, requestedGzip, trailers, contentLen)
 	if err != nil {
 	if err != nil {
 		cc.mu.Unlock()
 		cc.mu.Unlock()
-		return nil, err
+		return nil, false, err
 	}
 	}
 
 
 	cs := cc.newStream()
 	cs := cc.newStream()
@@ -767,7 +830,7 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
 
 
 	cc.wmu.Lock()
 	cc.wmu.Lock()
 	endStream := !hasBody && !hasTrailers
 	endStream := !hasBody && !hasTrailers
-	werr := cc.writeHeaders(cs.ID, endStream, hdrs)
+	werr := cc.writeHeaders(cs.ID, endStream, int(cc.maxFrameSize), hdrs)
 	cc.wmu.Unlock()
 	cc.wmu.Unlock()
 	traceWroteHeaders(cs.trace)
 	traceWroteHeaders(cs.trace)
 	cc.mu.Unlock()
 	cc.mu.Unlock()
@@ -781,7 +844,7 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
 		// Don't bother sending a RST_STREAM (our write already failed;
 		// Don't bother sending a RST_STREAM (our write already failed;
 		// no need to keep writing)
 		// no need to keep writing)
 		traceWroteRequest(cs.trace, werr)
 		traceWroteRequest(cs.trace, werr)
-		return nil, werr
+		return nil, false, werr
 	}
 	}
 
 
 	var respHeaderTimer <-chan time.Time
 	var respHeaderTimer <-chan time.Time
@@ -800,7 +863,7 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
 	bodyWritten := false
 	bodyWritten := false
 	ctx := reqContext(req)
 	ctx := reqContext(req)
 
 
-	handleReadLoopResponse := func(re resAndError) (*http.Response, error) {
+	handleReadLoopResponse := func(re resAndError) (*http.Response, bool, error) {
 		res := re.res
 		res := re.res
 		if re.err != nil || res.StatusCode > 299 {
 		if re.err != nil || res.StatusCode > 299 {
 			// On error or status code 3xx, 4xx, 5xx, etc abort any
 			// On error or status code 3xx, 4xx, 5xx, etc abort any
@@ -816,19 +879,12 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
 			cs.abortRequestBodyWrite(errStopReqBodyWrite)
 			cs.abortRequestBodyWrite(errStopReqBodyWrite)
 		}
 		}
 		if re.err != nil {
 		if re.err != nil {
-			if re.err == errClientConnGotGoAway {
-				cc.mu.Lock()
-				if cs.startedWrite {
-					re.err = errClientConnGotGoAwayAfterSomeReqBody
-				}
-				cc.mu.Unlock()
-			}
 			cc.forgetStreamID(cs.ID)
 			cc.forgetStreamID(cs.ID)
-			return nil, re.err
+			return nil, cs.getStartedWrite(), re.err
 		}
 		}
 		res.Request = req
 		res.Request = req
 		res.TLS = cc.tlsState
 		res.TLS = cc.tlsState
-		return res, nil
+		return res, false, nil
 	}
 	}
 
 
 	for {
 	for {
@@ -836,37 +892,37 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
 		case re := <-readLoopResCh:
 		case re := <-readLoopResCh:
 			return handleReadLoopResponse(re)
 			return handleReadLoopResponse(re)
 		case <-respHeaderTimer:
 		case <-respHeaderTimer:
-			cc.forgetStreamID(cs.ID)
 			if !hasBody || bodyWritten {
 			if !hasBody || bodyWritten {
 				cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
 				cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
 			} else {
 			} else {
 				bodyWriter.cancel()
 				bodyWriter.cancel()
 				cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel)
 				cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel)
 			}
 			}
-			return nil, errTimeout
-		case <-ctx.Done():
 			cc.forgetStreamID(cs.ID)
 			cc.forgetStreamID(cs.ID)
+			return nil, cs.getStartedWrite(), errTimeout
+		case <-ctx.Done():
 			if !hasBody || bodyWritten {
 			if !hasBody || bodyWritten {
 				cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
 				cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
 			} else {
 			} else {
 				bodyWriter.cancel()
 				bodyWriter.cancel()
 				cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel)
 				cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel)
 			}
 			}
-			return nil, ctx.Err()
-		case <-req.Cancel:
 			cc.forgetStreamID(cs.ID)
 			cc.forgetStreamID(cs.ID)
+			return nil, cs.getStartedWrite(), ctx.Err()
+		case <-req.Cancel:
 			if !hasBody || bodyWritten {
 			if !hasBody || bodyWritten {
 				cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
 				cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
 			} else {
 			} else {
 				bodyWriter.cancel()
 				bodyWriter.cancel()
 				cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel)
 				cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel)
 			}
 			}
-			return nil, errRequestCanceled
+			cc.forgetStreamID(cs.ID)
+			return nil, cs.getStartedWrite(), errRequestCanceled
 		case <-cs.peerReset:
 		case <-cs.peerReset:
 			// processResetStream already removed the
 			// processResetStream already removed the
 			// stream from the streams map; no need for
 			// stream from the streams map; no need for
 			// forgetStreamID.
 			// forgetStreamID.
-			return nil, cs.resetErr
+			return nil, cs.getStartedWrite(), cs.resetErr
 		case err := <-bodyWriter.resc:
 		case err := <-bodyWriter.resc:
 			// Prefer the read loop's response, if available. Issue 16102.
 			// Prefer the read loop's response, if available. Issue 16102.
 			select {
 			select {
@@ -875,7 +931,7 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
 			default:
 			default:
 			}
 			}
 			if err != nil {
 			if err != nil {
-				return nil, err
+				return nil, cs.getStartedWrite(), err
 			}
 			}
 			bodyWritten = true
 			bodyWritten = true
 			if d := cc.responseHeaderTimeout(); d != 0 {
 			if d := cc.responseHeaderTimeout(); d != 0 {
@@ -887,14 +943,55 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
 	}
 	}
 }
 }
 
 
+// awaitOpenSlotForRequest waits until len(streams) < maxConcurrentStreams.
+// Must hold cc.mu.
+func (cc *ClientConn) awaitOpenSlotForRequest(req *http.Request) error {
+	var waitingForConn chan struct{}
+	var waitingForConnErr error // guarded by cc.mu
+	for {
+		cc.lastActive = time.Now()
+		if cc.closed || !cc.canTakeNewRequestLocked() {
+			if waitingForConn != nil {
+				close(waitingForConn)
+			}
+			return errClientConnUnusable
+		}
+		if int64(len(cc.streams))+1 <= int64(cc.maxConcurrentStreams) {
+			if waitingForConn != nil {
+				close(waitingForConn)
+			}
+			return nil
+		}
+		// Unfortunately, we cannot wait on a condition variable and channel at
+		// the same time, so instead, we spin up a goroutine to check if the
+		// request is canceled while we wait for a slot to open in the connection.
+		if waitingForConn == nil {
+			waitingForConn = make(chan struct{})
+			go func() {
+				if err := awaitRequestCancel(req, waitingForConn); err != nil {
+					cc.mu.Lock()
+					waitingForConnErr = err
+					cc.cond.Broadcast()
+					cc.mu.Unlock()
+				}
+			}()
+		}
+		cc.pendingRequests++
+		cc.cond.Wait()
+		cc.pendingRequests--
+		if waitingForConnErr != nil {
+			return waitingForConnErr
+		}
+	}
+}
+
 // requires cc.wmu be held
 // requires cc.wmu be held
-func (cc *ClientConn) writeHeaders(streamID uint32, endStream bool, hdrs []byte) error {
+func (cc *ClientConn) writeHeaders(streamID uint32, endStream bool, maxFrameSize int, hdrs []byte) error {
 	first := true // first frame written (HEADERS is first, then CONTINUATION)
 	first := true // first frame written (HEADERS is first, then CONTINUATION)
-	frameSize := int(cc.maxFrameSize)
 	for len(hdrs) > 0 && cc.werr == nil {
 	for len(hdrs) > 0 && cc.werr == nil {
 		chunk := hdrs
 		chunk := hdrs
-		if len(chunk) > frameSize {
-			chunk = chunk[:frameSize]
+		if len(chunk) > maxFrameSize {
+			chunk = chunk[:maxFrameSize]
 		}
 		}
 		hdrs = hdrs[len(chunk):]
 		hdrs = hdrs[len(chunk):]
 		endHeaders := len(hdrs) == 0
 		endHeaders := len(hdrs) == 0
@@ -1002,17 +1099,26 @@ func (cs *clientStream) writeRequestBody(body io.Reader, bodyCloser io.Closer) (
 	var trls []byte
 	var trls []byte
 	if hasTrailers {
 	if hasTrailers {
 		cc.mu.Lock()
 		cc.mu.Lock()
-		defer cc.mu.Unlock()
-		trls = cc.encodeTrailers(req)
+		trls, err = cc.encodeTrailers(req)
+		cc.mu.Unlock()
+		if err != nil {
+			cc.writeStreamReset(cs.ID, ErrCodeInternal, err)
+			cc.forgetStreamID(cs.ID)
+			return err
+		}
 	}
 	}
 
 
+	cc.mu.Lock()
+	maxFrameSize := int(cc.maxFrameSize)
+	cc.mu.Unlock()
+
 	cc.wmu.Lock()
 	cc.wmu.Lock()
 	defer cc.wmu.Unlock()
 	defer cc.wmu.Unlock()
 
 
 	// Two ways to send END_STREAM: either with trailers, or
 	// Two ways to send END_STREAM: either with trailers, or
 	// with an empty DATA frame.
 	// with an empty DATA frame.
 	if len(trls) > 0 {
 	if len(trls) > 0 {
-		err = cc.writeHeaders(cs.ID, true, trls)
+		err = cc.writeHeaders(cs.ID, true, maxFrameSize, trls)
 	} else {
 	} else {
 		err = cc.fr.WriteData(cs.ID, true, nil)
 		err = cc.fr.WriteData(cs.ID, true, nil)
 	}
 	}
@@ -1106,62 +1212,86 @@ func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trail
 		}
 		}
 	}
 	}
 
 
-	// 8.1.2.3 Request Pseudo-Header Fields
-	// The :path pseudo-header field includes the path and query parts of the
-	// target URI (the path-absolute production and optionally a '?' character
-	// followed by the query production (see Sections 3.3 and 3.4 of
-	// [RFC3986]).
-	cc.writeHeader(":authority", host)
-	cc.writeHeader(":method", req.Method)
-	if req.Method != "CONNECT" {
-		cc.writeHeader(":path", path)
-		cc.writeHeader(":scheme", req.URL.Scheme)
-	}
-	if trailers != "" {
-		cc.writeHeader("trailer", trailers)
-	}
+	enumerateHeaders := func(f func(name, value string)) {
+		// 8.1.2.3 Request Pseudo-Header Fields
+		// The :path pseudo-header field includes the path and query parts of the
+		// target URI (the path-absolute production and optionally a '?' character
+		// followed by the query production (see Sections 3.3 and 3.4 of
+		// [RFC3986]).
+		f(":authority", host)
+		f(":method", req.Method)
+		if req.Method != "CONNECT" {
+			f(":path", path)
+			f(":scheme", req.URL.Scheme)
+		}
+		if trailers != "" {
+			f("trailer", trailers)
+		}
 
 
-	var didUA bool
-	for k, vv := range req.Header {
-		lowKey := strings.ToLower(k)
-		switch lowKey {
-		case "host", "content-length":
-			// Host is :authority, already sent.
-			// Content-Length is automatic, set below.
-			continue
-		case "connection", "proxy-connection", "transfer-encoding", "upgrade", "keep-alive":
-			// Per 8.1.2.2 Connection-Specific Header
-			// Fields, don't send connection-specific
-			// fields. We have already checked if any
-			// are error-worthy so just ignore the rest.
-			continue
-		case "user-agent":
-			// Match Go's http1 behavior: at most one
-			// User-Agent. If set to nil or empty string,
-			// then omit it. Otherwise if not mentioned,
-			// include the default (below).
-			didUA = true
-			if len(vv) < 1 {
+		var didUA bool
+		for k, vv := range req.Header {
+			if strings.EqualFold(k, "host") || strings.EqualFold(k, "content-length") {
+				// Host is :authority, already sent.
+				// Content-Length is automatic, set below.
 				continue
 				continue
-			}
-			vv = vv[:1]
-			if vv[0] == "" {
+			} else if strings.EqualFold(k, "connection") || strings.EqualFold(k, "proxy-connection") ||
+				strings.EqualFold(k, "transfer-encoding") || strings.EqualFold(k, "upgrade") ||
+				strings.EqualFold(k, "keep-alive") {
+				// Per 8.1.2.2 Connection-Specific Header
+				// Fields, don't send connection-specific
+				// fields. We have already checked if any
+				// are error-worthy so just ignore the rest.
 				continue
 				continue
+			} else if strings.EqualFold(k, "user-agent") {
+				// Match Go's http1 behavior: at most one
+				// User-Agent. If set to nil or empty string,
+				// then omit it. Otherwise if not mentioned,
+				// include the default (below).
+				didUA = true
+				if len(vv) < 1 {
+					continue
+				}
+				vv = vv[:1]
+				if vv[0] == "" {
+					continue
+				}
+
+			}
+
+			for _, v := range vv {
+				f(k, v)
 			}
 			}
 		}
 		}
-		for _, v := range vv {
-			cc.writeHeader(lowKey, v)
+		if shouldSendReqContentLength(req.Method, contentLength) {
+			f("content-length", strconv.FormatInt(contentLength, 10))
+		}
+		if addGzipHeader {
+			f("accept-encoding", "gzip")
+		}
+		if !didUA {
+			f("user-agent", defaultUserAgent)
 		}
 		}
 	}
 	}
-	if shouldSendReqContentLength(req.Method, contentLength) {
-		cc.writeHeader("content-length", strconv.FormatInt(contentLength, 10))
-	}
-	if addGzipHeader {
-		cc.writeHeader("accept-encoding", "gzip")
-	}
-	if !didUA {
-		cc.writeHeader("user-agent", defaultUserAgent)
+
+	// Do a first pass over the headers counting bytes to ensure
+	// we don't exceed cc.peerMaxHeaderListSize. This is done as a
+	// separate pass before encoding the headers to prevent
+	// modifying the hpack state.
+	hlSize := uint64(0)
+	enumerateHeaders(func(name, value string) {
+		hf := hpack.HeaderField{Name: name, Value: value}
+		hlSize += uint64(hf.Size())
+	})
+
+	if hlSize > cc.peerMaxHeaderListSize {
+		return nil, errRequestHeaderListSize
 	}
 	}
+
+	// Header list size is ok. Write the headers.
+	enumerateHeaders(func(name, value string) {
+		cc.writeHeader(strings.ToLower(name), value)
+	})
+
 	return cc.hbuf.Bytes(), nil
 	return cc.hbuf.Bytes(), nil
 }
 }
 
 
@@ -1188,17 +1318,29 @@ func shouldSendReqContentLength(method string, contentLength int64) bool {
 }
 }
 
 
 // requires cc.mu be held.
 // requires cc.mu be held.
-func (cc *ClientConn) encodeTrailers(req *http.Request) []byte {
+func (cc *ClientConn) encodeTrailers(req *http.Request) ([]byte, error) {
 	cc.hbuf.Reset()
 	cc.hbuf.Reset()
+
+	hlSize := uint64(0)
 	for k, vv := range req.Trailer {
 	for k, vv := range req.Trailer {
-		// Transfer-Encoding, etc.. have already been filter at the
+		for _, v := range vv {
+			hf := hpack.HeaderField{Name: k, Value: v}
+			hlSize += uint64(hf.Size())
+		}
+	}
+	if hlSize > cc.peerMaxHeaderListSize {
+		return nil, errRequestHeaderListSize
+	}
+
+	for k, vv := range req.Trailer {
+		// Transfer-Encoding, etc.. have already been filtered at the
 		// start of RoundTrip
 		// start of RoundTrip
 		lowKey := strings.ToLower(k)
 		lowKey := strings.ToLower(k)
 		for _, v := range vv {
 		for _, v := range vv {
 			cc.writeHeader(lowKey, v)
 			cc.writeHeader(lowKey, v)
 		}
 		}
 	}
 	}
-	return cc.hbuf.Bytes()
+	return cc.hbuf.Bytes(), nil
 }
 }
 
 
 func (cc *ClientConn) writeHeader(name, value string) {
 func (cc *ClientConn) writeHeader(name, value string) {
@@ -1246,7 +1388,9 @@ func (cc *ClientConn) streamByID(id uint32, andRemove bool) *clientStream {
 			cc.idleTimer.Reset(cc.idleTimeout)
 			cc.idleTimer.Reset(cc.idleTimeout)
 		}
 		}
 		close(cs.done)
 		close(cs.done)
-		cc.cond.Broadcast() // wake up checkResetOrDone via clientStream.awaitFlowControl
+		// Wake up checkResetOrDone via clientStream.awaitFlowControl and
+		// wake up RoundTrip if there is a pending request.
+		cc.cond.Broadcast()
 	}
 	}
 	return cs
 	return cs
 }
 }
@@ -1254,17 +1398,12 @@ func (cc *ClientConn) streamByID(id uint32, andRemove bool) *clientStream {
 // clientConnReadLoop is the state owned by the clientConn's frame-reading readLoop.
 // clientConnReadLoop is the state owned by the clientConn's frame-reading readLoop.
 type clientConnReadLoop struct {
 type clientConnReadLoop struct {
 	cc            *ClientConn
 	cc            *ClientConn
-	activeRes     map[uint32]*clientStream // keyed by streamID
 	closeWhenIdle bool
 	closeWhenIdle bool
 }
 }
 
 
 // readLoop runs in its own goroutine and reads and dispatches frames.
 // readLoop runs in its own goroutine and reads and dispatches frames.
 func (cc *ClientConn) readLoop() {
 func (cc *ClientConn) readLoop() {
-	rl := &clientConnReadLoop{
-		cc:        cc,
-		activeRes: make(map[uint32]*clientStream),
-	}
-
+	rl := &clientConnReadLoop{cc: cc}
 	defer rl.cleanup()
 	defer rl.cleanup()
 	cc.readerErr = rl.run()
 	cc.readerErr = rl.run()
 	if ce, ok := cc.readerErr.(ConnectionError); ok {
 	if ce, ok := cc.readerErr.(ConnectionError); ok {
@@ -1319,10 +1458,8 @@ func (rl *clientConnReadLoop) cleanup() {
 	} else if err == io.EOF {
 	} else if err == io.EOF {
 		err = io.ErrUnexpectedEOF
 		err = io.ErrUnexpectedEOF
 	}
 	}
-	for _, cs := range rl.activeRes {
-		cs.bufPipe.CloseWithError(err)
-	}
 	for _, cs := range cc.streams {
 	for _, cs := range cc.streams {
+		cs.bufPipe.CloseWithError(err) // no-op if already closed
 		select {
 		select {
 		case cs.resc <- resAndError{err: err}:
 		case cs.resc <- resAndError{err: err}:
 		default:
 		default:
@@ -1345,8 +1482,9 @@ func (rl *clientConnReadLoop) run() error {
 			cc.vlogf("http2: Transport readFrame error on conn %p: (%T) %v", cc, err, err)
 			cc.vlogf("http2: Transport readFrame error on conn %p: (%T) %v", cc, err, err)
 		}
 		}
 		if se, ok := err.(StreamError); ok {
 		if se, ok := err.(StreamError); ok {
-			if cs := cc.streamByID(se.StreamID, true /*ended; remove it*/); cs != nil {
+			if cs := cc.streamByID(se.StreamID, false); cs != nil {
 				cs.cc.writeStreamReset(cs.ID, se.Code, err)
 				cs.cc.writeStreamReset(cs.ID, se.Code, err)
+				cs.cc.forgetStreamID(cs.ID)
 				if se.Cause == nil {
 				if se.Cause == nil {
 					se.Cause = cc.fr.errDetail
 					se.Cause = cc.fr.errDetail
 				}
 				}
@@ -1399,7 +1537,7 @@ func (rl *clientConnReadLoop) run() error {
 			}
 			}
 			return err
 			return err
 		}
 		}
-		if rl.closeWhenIdle && gotReply && maybeIdle && len(rl.activeRes) == 0 {
+		if rl.closeWhenIdle && gotReply && maybeIdle {
 			cc.closeIfIdle()
 			cc.closeIfIdle()
 		}
 		}
 	}
 	}
@@ -1407,13 +1545,31 @@ func (rl *clientConnReadLoop) run() error {
 
 
 func (rl *clientConnReadLoop) processHeaders(f *MetaHeadersFrame) error {
 func (rl *clientConnReadLoop) processHeaders(f *MetaHeadersFrame) error {
 	cc := rl.cc
 	cc := rl.cc
-	cs := cc.streamByID(f.StreamID, f.StreamEnded())
+	cs := cc.streamByID(f.StreamID, false)
 	if cs == nil {
 	if cs == nil {
 		// We'd get here if we canceled a request while the
 		// We'd get here if we canceled a request while the
 		// server had its response still in flight. So if this
 		// server had its response still in flight. So if this
 		// was just something we canceled, ignore it.
 		// was just something we canceled, ignore it.
 		return nil
 		return nil
 	}
 	}
+	if f.StreamEnded() {
+		// Issue 20521: If the stream has ended, streamByID() causes
+		// clientStream.done to be closed, which causes the request's bodyWriter
+		// to be closed with an errStreamClosed, which may be received by
+		// clientConn.RoundTrip before the result of processing these headers.
+		// Deferring stream closure allows the header processing to occur first.
+		// clientConn.RoundTrip may still receive the bodyWriter error first, but
+		// the fix for issue 16102 prioritises any response.
+		//
+		// Issue 22413: If there is no request body, we should close the
+		// stream before writing to cs.resc so that the stream is closed
+		// immediately once RoundTrip returns.
+		if cs.req.Body != nil {
+			defer cc.forgetStreamID(f.StreamID)
+		} else {
+			cc.forgetStreamID(f.StreamID)
+		}
+	}
 	if !cs.firstByte {
 	if !cs.firstByte {
 		if cs.trace != nil {
 		if cs.trace != nil {
 			// TODO(bradfitz): move first response byte earlier,
 			// TODO(bradfitz): move first response byte earlier,
@@ -1437,6 +1593,7 @@ func (rl *clientConnReadLoop) processHeaders(f *MetaHeadersFrame) error {
 		}
 		}
 		// Any other error type is a stream error.
 		// Any other error type is a stream error.
 		cs.cc.writeStreamReset(f.StreamID, ErrCodeProtocol, err)
 		cs.cc.writeStreamReset(f.StreamID, ErrCodeProtocol, err)
+		cc.forgetStreamID(cs.ID)
 		cs.resc <- resAndError{err: err}
 		cs.resc <- resAndError{err: err}
 		return nil // return nil from process* funcs to keep conn alive
 		return nil // return nil from process* funcs to keep conn alive
 	}
 	}
@@ -1444,9 +1601,6 @@ func (rl *clientConnReadLoop) processHeaders(f *MetaHeadersFrame) error {
 		// (nil, nil) special case. See handleResponse docs.
 		// (nil, nil) special case. See handleResponse docs.
 		return nil
 		return nil
 	}
 	}
-	if res.Body != noBody {
-		rl.activeRes[cs.ID] = cs
-	}
 	cs.resTrailer = &res.Trailer
 	cs.resTrailer = &res.Trailer
 	cs.resc <- resAndError{res: res}
 	cs.resc <- resAndError{res: res}
 	return nil
 	return nil
@@ -1466,11 +1620,11 @@ func (rl *clientConnReadLoop) handleResponse(cs *clientStream, f *MetaHeadersFra
 
 
 	status := f.PseudoValue("status")
 	status := f.PseudoValue("status")
 	if status == "" {
 	if status == "" {
-		return nil, errors.New("missing status pseudo header")
+		return nil, errors.New("malformed response from server: missing status pseudo header")
 	}
 	}
 	statusCode, err := strconv.Atoi(status)
 	statusCode, err := strconv.Atoi(status)
 	if err != nil {
 	if err != nil {
-		return nil, errors.New("malformed non-numeric status pseudo header")
+		return nil, errors.New("malformed response from server: malformed non-numeric status pseudo header")
 	}
 	}
 
 
 	if statusCode == 100 {
 	if statusCode == 100 {
@@ -1668,6 +1822,7 @@ func (b transportResponseBody) Close() error {
 	}
 	}
 
 
 	cs.bufPipe.BreakWithError(errClosedResponseBody)
 	cs.bufPipe.BreakWithError(errClosedResponseBody)
+	cc.forgetStreamID(cs.ID)
 	return nil
 	return nil
 }
 }
 
 
@@ -1702,7 +1857,23 @@ func (rl *clientConnReadLoop) processData(f *DataFrame) error {
 		}
 		}
 		return nil
 		return nil
 	}
 	}
+	if !cs.firstByte {
+		cc.logf("protocol error: received DATA before a HEADERS frame")
+		rl.endStreamError(cs, StreamError{
+			StreamID: f.StreamID,
+			Code:     ErrCodeProtocol,
+		})
+		return nil
+	}
 	if f.Length > 0 {
 	if f.Length > 0 {
+		if cs.req.Method == "HEAD" && len(data) > 0 {
+			cc.logf("protocol error: received DATA on a HEAD request")
+			rl.endStreamError(cs, StreamError{
+				StreamID: f.StreamID,
+				Code:     ErrCodeProtocol,
+			})
+			return nil
+		}
 		// Check connection-level flow control.
 		// Check connection-level flow control.
 		cc.mu.Lock()
 		cc.mu.Lock()
 		if cs.inflow.available() >= int32(f.Length) {
 		if cs.inflow.available() >= int32(f.Length) {
@@ -1713,16 +1884,27 @@ func (rl *clientConnReadLoop) processData(f *DataFrame) error {
 		}
 		}
 		// Return any padded flow control now, since we won't
 		// Return any padded flow control now, since we won't
 		// refund it later on body reads.
 		// refund it later on body reads.
-		if pad := int32(f.Length) - int32(len(data)); pad > 0 {
-			cs.inflow.add(pad)
-			cc.inflow.add(pad)
+		var refund int
+		if pad := int(f.Length) - len(data); pad > 0 {
+			refund += pad
+		}
+		// Return len(data) now if the stream is already closed,
+		// since data will never be read.
+		didReset := cs.didReset
+		if didReset {
+			refund += len(data)
+		}
+		if refund > 0 {
+			cc.inflow.add(int32(refund))
 			cc.wmu.Lock()
 			cc.wmu.Lock()
-			cc.fr.WriteWindowUpdate(0, uint32(pad))
-			cc.fr.WriteWindowUpdate(cs.ID, uint32(pad))
+			cc.fr.WriteWindowUpdate(0, uint32(refund))
+			if !didReset {
+				cs.inflow.add(int32(refund))
+				cc.fr.WriteWindowUpdate(cs.ID, uint32(refund))
+			}
 			cc.bw.Flush()
 			cc.bw.Flush()
 			cc.wmu.Unlock()
 			cc.wmu.Unlock()
 		}
 		}
-		didReset := cs.didReset
 		cc.mu.Unlock()
 		cc.mu.Unlock()
 
 
 		if len(data) > 0 && !didReset {
 		if len(data) > 0 && !didReset {
@@ -1753,11 +1935,10 @@ func (rl *clientConnReadLoop) endStreamError(cs *clientStream, err error) {
 		err = io.EOF
 		err = io.EOF
 		code = cs.copyTrailers
 		code = cs.copyTrailers
 	}
 	}
-	cs.bufPipe.closeWithErrorAndCode(err, code)
-	delete(rl.activeRes, cs.ID)
 	if isConnectionCloseRequest(cs.req) {
 	if isConnectionCloseRequest(cs.req) {
 		rl.closeWhenIdle = true
 		rl.closeWhenIdle = true
 	}
 	}
+	cs.bufPipe.closeWithErrorAndCode(err, code)
 
 
 	select {
 	select {
 	case cs.resc <- resAndError{err: err}:
 	case cs.resc <- resAndError{err: err}:
@@ -1805,6 +1986,8 @@ func (rl *clientConnReadLoop) processSettings(f *SettingsFrame) error {
 			cc.maxFrameSize = s.Val
 			cc.maxFrameSize = s.Val
 		case SettingMaxConcurrentStreams:
 		case SettingMaxConcurrentStreams:
 			cc.maxConcurrentStreams = s.Val
 			cc.maxConcurrentStreams = s.Val
+		case SettingMaxHeaderListSize:
+			cc.peerMaxHeaderListSize = uint64(s.Val)
 		case SettingInitialWindowSize:
 		case SettingInitialWindowSize:
 			// Values above the maximum flow-control
 			// Values above the maximum flow-control
 			// window size of 2^31-1 MUST be treated as a
 			// window size of 2^31-1 MUST be treated as a
@@ -1882,7 +2065,6 @@ func (rl *clientConnReadLoop) processResetStream(f *RSTStreamFrame) error {
 		cs.bufPipe.CloseWithError(err)
 		cs.bufPipe.CloseWithError(err)
 		cs.cc.cond.Broadcast() // wake up checkResetOrDone via clientStream.awaitFlowControl
 		cs.cc.cond.Broadcast() // wake up checkResetOrDone via clientStream.awaitFlowControl
 	}
 	}
-	delete(rl.activeRes, cs.ID)
 	return nil
 	return nil
 }
 }
 
 
@@ -1971,6 +2153,7 @@ func (cc *ClientConn) writeStreamReset(streamID uint32, code ErrCode, err error)
 
 
 var (
 var (
 	errResponseHeaderListSize = errors.New("http2: response header list larger than advertised limit")
 	errResponseHeaderListSize = errors.New("http2: response header list larger than advertised limit")
+	errRequestHeaderListSize  = errors.New("http2: request header list larger than peer's advertised limit")
 	errPseudoTrailers         = errors.New("http2: invalid pseudo header in trailers")
 	errPseudoTrailers         = errors.New("http2: invalid pseudo header in trailers")
 )
 )
 
 

+ 895 - 19
vendor/golang.org/x/net/http2/transport_test.go

@@ -13,9 +13,11 @@ import (
 	"fmt"
 	"fmt"
 	"io"
 	"io"
 	"io/ioutil"
 	"io/ioutil"
+	"log"
 	"math/rand"
 	"math/rand"
 	"net"
 	"net"
 	"net/http"
 	"net/http"
+	"net/http/httptest"
 	"net/url"
 	"net/url"
 	"os"
 	"os"
 	"reflect"
 	"reflect"
@@ -417,6 +419,11 @@ func TestActualContentLength(t *testing.T) {
 			req:  &http.Request{Body: panicReader{}, ContentLength: 5},
 			req:  &http.Request{Body: panicReader{}, ContentLength: 5},
 			want: 5,
 			want: 5,
 		},
 		},
+		// http.NoBody means 0, not -1.
+		3: {
+			req:  &http.Request{Body: go18httpNoBody()},
+			want: 0,
+		},
 	}
 	}
 	for i, tt := range tests {
 	for i, tt := range tests {
 		got := actualContentLength(tt.req)
 		got := actualContentLength(tt.req)
@@ -680,7 +687,7 @@ func newLocalListener(t *testing.T) net.Listener {
 	return ln
 	return ln
 }
 }
 
 
-func (ct *clientTester) greet() {
+func (ct *clientTester) greet(settings ...Setting) {
 	buf := make([]byte, len(ClientPreface))
 	buf := make([]byte, len(ClientPreface))
 	_, err := io.ReadFull(ct.sc, buf)
 	_, err := io.ReadFull(ct.sc, buf)
 	if err != nil {
 	if err != nil {
@@ -694,7 +701,7 @@ func (ct *clientTester) greet() {
 		ct.t.Fatalf("Wanted client settings frame; got %v", f)
 		ct.t.Fatalf("Wanted client settings frame; got %v", f)
 		_ = sf // stash it away?
 		_ = sf // stash it away?
 	}
 	}
-	if err := ct.fr.WriteSettings(); err != nil {
+	if err := ct.fr.WriteSettings(settings...); err != nil {
 		ct.t.Fatal(err)
 		ct.t.Fatal(err)
 	}
 	}
 	if err := ct.fr.WriteSettingsAck(); err != nil {
 	if err := ct.fr.WriteSettingsAck(); err != nil {
@@ -1365,6 +1372,269 @@ func testInvalidTrailer(t *testing.T, trailers headerType, wantErr error, writeT
 	ct.run()
 	ct.run()
 }
 }
 
 
+// headerListSize returns the HTTP2 header list size of h.
+//   http://httpwg.org/specs/rfc7540.html#SETTINGS_MAX_HEADER_LIST_SIZE
+//   http://httpwg.org/specs/rfc7540.html#MaxHeaderBlock
+func headerListSize(h http.Header) (size uint32) {
+	for k, vv := range h {
+		for _, v := range vv {
+			hf := hpack.HeaderField{Name: k, Value: v}
+			size += hf.Size()
+		}
+	}
+	return size
+}
+
+// padHeaders adds data to an http.Header until headerListSize(h) ==
+// limit. Due to the way header list sizes are calculated, padHeaders
+// cannot add fewer than len("Pad-Headers") + 32 bytes to h, and will
+// call t.Fatal if asked to do so. PadHeaders first reserves enough
+// space for an empty "Pad-Headers" key, then adds as many copies of
+// filler as possible. Any remaining bytes necessary to push the
+// header list size up to limit are added to h["Pad-Headers"].
+func padHeaders(t *testing.T, h http.Header, limit uint64, filler string) {
+	if limit > 0xffffffff {
+		t.Fatalf("padHeaders: refusing to pad to more than 2^32-1 bytes. limit = %v", limit)
+	}
+	hf := hpack.HeaderField{Name: "Pad-Headers", Value: ""}
+	minPadding := uint64(hf.Size())
+	size := uint64(headerListSize(h))
+
+	minlimit := size + minPadding
+	if limit < minlimit {
+		t.Fatalf("padHeaders: limit %v < %v", limit, minlimit)
+	}
+
+	// Use a fixed-width format for name so that fieldSize
+	// remains constant.
+	nameFmt := "Pad-Headers-%06d"
+	hf = hpack.HeaderField{Name: fmt.Sprintf(nameFmt, 1), Value: filler}
+	fieldSize := uint64(hf.Size())
+
+	// Add as many complete filler values as possible, leaving
+	// room for at least one empty "Pad-Headers" key.
+	limit = limit - minPadding
+	for i := 0; size+fieldSize < limit; i++ {
+		name := fmt.Sprintf(nameFmt, i)
+		h.Add(name, filler)
+		size += fieldSize
+	}
+
+	// Add enough bytes to reach limit.
+	remain := limit - size
+	lastValue := strings.Repeat("*", int(remain))
+	h.Add("Pad-Headers", lastValue)
+}
+
+func TestPadHeaders(t *testing.T) {
+	check := func(h http.Header, limit uint32, fillerLen int) {
+		if h == nil {
+			h = make(http.Header)
+		}
+		filler := strings.Repeat("f", fillerLen)
+		padHeaders(t, h, uint64(limit), filler)
+		gotSize := headerListSize(h)
+		if gotSize != limit {
+			t.Errorf("Got size = %v; want %v", gotSize, limit)
+		}
+	}
+	// Try all possible combinations for small fillerLen and limit.
+	hf := hpack.HeaderField{Name: "Pad-Headers", Value: ""}
+	minLimit := hf.Size()
+	for limit := minLimit; limit <= 128; limit++ {
+		for fillerLen := 0; uint32(fillerLen) <= limit; fillerLen++ {
+			check(nil, limit, fillerLen)
+		}
+	}
+
+	// Try a few tests with larger limits, plus cumulative
+	// tests. Since these tests are cumulative, tests[i+1].limit
+	// must be >= tests[i].limit + minLimit. See the comment on
+	// padHeaders for more info on why the limit arg has this
+	// restriction.
+	tests := []struct {
+		fillerLen int
+		limit     uint32
+	}{
+		{
+			fillerLen: 64,
+			limit:     1024,
+		},
+		{
+			fillerLen: 1024,
+			limit:     1286,
+		},
+		{
+			fillerLen: 256,
+			limit:     2048,
+		},
+		{
+			fillerLen: 1024,
+			limit:     10 * 1024,
+		},
+		{
+			fillerLen: 1023,
+			limit:     11 * 1024,
+		},
+	}
+	h := make(http.Header)
+	for _, tc := range tests {
+		check(nil, tc.limit, tc.fillerLen)
+		check(h, tc.limit, tc.fillerLen)
+	}
+}
+
+func TestTransportChecksRequestHeaderListSize(t *testing.T) {
+	st := newServerTester(t,
+		func(w http.ResponseWriter, r *http.Request) {
+			// Consume body & force client to send
+			// trailers before writing response.
+			// ioutil.ReadAll returns non-nil err for
+			// requests that attempt to send greater than
+			// maxHeaderListSize bytes of trailers, since
+			// those requests generate a stream reset.
+			ioutil.ReadAll(r.Body)
+			r.Body.Close()
+		},
+		func(ts *httptest.Server) {
+			ts.Config.MaxHeaderBytes = 16 << 10
+		},
+		optOnlyServer,
+		optQuiet,
+	)
+	defer st.Close()
+
+	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
+	defer tr.CloseIdleConnections()
+
+	checkRoundTrip := func(req *http.Request, wantErr error, desc string) {
+		res, err := tr.RoundTrip(req)
+		if err != wantErr {
+			if res != nil {
+				res.Body.Close()
+			}
+			t.Errorf("%v: RoundTrip err = %v; want %v", desc, err, wantErr)
+			return
+		}
+		if err == nil {
+			if res == nil {
+				t.Errorf("%v: response nil; want non-nil.", desc)
+				return
+			}
+			defer res.Body.Close()
+			if res.StatusCode != http.StatusOK {
+				t.Errorf("%v: response status = %v; want %v", desc, res.StatusCode, http.StatusOK)
+			}
+			return
+		}
+		if res != nil {
+			t.Errorf("%v: RoundTrip err = %v but response non-nil", desc, err)
+		}
+	}
+	headerListSizeForRequest := func(req *http.Request) (size uint64) {
+		contentLen := actualContentLength(req)
+		trailers, err := commaSeparatedTrailers(req)
+		if err != nil {
+			t.Fatalf("headerListSizeForRequest: %v", err)
+		}
+		cc := &ClientConn{peerMaxHeaderListSize: 0xffffffffffffffff}
+		cc.henc = hpack.NewEncoder(&cc.hbuf)
+		cc.mu.Lock()
+		hdrs, err := cc.encodeHeaders(req, true, trailers, contentLen)
+		cc.mu.Unlock()
+		if err != nil {
+			t.Fatalf("headerListSizeForRequest: %v", err)
+		}
+		hpackDec := hpack.NewDecoder(initialHeaderTableSize, func(hf hpack.HeaderField) {
+			size += uint64(hf.Size())
+		})
+		if len(hdrs) > 0 {
+			if _, err := hpackDec.Write(hdrs); err != nil {
+				t.Fatalf("headerListSizeForRequest: %v", err)
+			}
+		}
+		return size
+	}
+	// Create a new Request for each test, rather than reusing the
+	// same Request, to avoid a race when modifying req.Headers.
+	// See https://github.com/golang/go/issues/21316
+	newRequest := func() *http.Request {
+		// Body must be non-nil to enable writing trailers.
+		body := strings.NewReader("hello")
+		req, err := http.NewRequest("POST", st.ts.URL, body)
+		if err != nil {
+			t.Fatalf("newRequest: NewRequest: %v", err)
+		}
+		return req
+	}
+
+	// Make an arbitrary request to ensure we get the server's
+	// settings frame and initialize peerMaxHeaderListSize.
+	req := newRequest()
+	checkRoundTrip(req, nil, "Initial request")
+
+	// Get the ClientConn associated with the request and validate
+	// peerMaxHeaderListSize.
+	addr := authorityAddr(req.URL.Scheme, req.URL.Host)
+	cc, err := tr.connPool().GetClientConn(req, addr)
+	if err != nil {
+		t.Fatalf("GetClientConn: %v", err)
+	}
+	cc.mu.Lock()
+	peerSize := cc.peerMaxHeaderListSize
+	cc.mu.Unlock()
+	st.scMu.Lock()
+	wantSize := uint64(st.sc.maxHeaderListSize())
+	st.scMu.Unlock()
+	if peerSize != wantSize {
+		t.Errorf("peerMaxHeaderListSize = %v; want %v", peerSize, wantSize)
+	}
+
+	// Sanity check peerSize. (*serverConn) maxHeaderListSize adds
+	// 320 bytes of padding.
+	wantHeaderBytes := uint64(st.ts.Config.MaxHeaderBytes) + 320
+	if peerSize != wantHeaderBytes {
+		t.Errorf("peerMaxHeaderListSize = %v; want %v.", peerSize, wantHeaderBytes)
+	}
+
+	// Pad headers & trailers, but stay under peerSize.
+	req = newRequest()
+	req.Header = make(http.Header)
+	req.Trailer = make(http.Header)
+	filler := strings.Repeat("*", 1024)
+	padHeaders(t, req.Trailer, peerSize, filler)
+	// cc.encodeHeaders adds some default headers to the request,
+	// so we need to leave room for those.
+	defaultBytes := headerListSizeForRequest(req)
+	padHeaders(t, req.Header, peerSize-defaultBytes, filler)
+	checkRoundTrip(req, nil, "Headers & Trailers under limit")
+
+	// Add enough header bytes to push us over peerSize.
+	req = newRequest()
+	req.Header = make(http.Header)
+	padHeaders(t, req.Header, peerSize, filler)
+	checkRoundTrip(req, errRequestHeaderListSize, "Headers over limit")
+
+	// Push trailers over the limit.
+	req = newRequest()
+	req.Trailer = make(http.Header)
+	padHeaders(t, req.Trailer, peerSize+1, filler)
+	checkRoundTrip(req, errRequestHeaderListSize, "Trailers over limit")
+
+	// Send headers with a single large value.
+	req = newRequest()
+	filler = strings.Repeat("*", int(peerSize))
+	req.Header = make(http.Header)
+	req.Header.Set("Big", filler)
+	checkRoundTrip(req, errRequestHeaderListSize, "Single large header")
+
+	// Send trailers with a single large value.
+	req = newRequest()
+	req.Trailer = make(http.Header)
+	req.Trailer.Set("Big", filler)
+	checkRoundTrip(req, errRequestHeaderListSize, "Single large trailer")
+}
+
 func TestTransportChecksResponseHeaderListSize(t *testing.T) {
 func TestTransportChecksResponseHeaderListSize(t *testing.T) {
 	ct := newClientTester(t)
 	ct := newClientTester(t)
 	ct.client = func() error {
 	ct.client = func() error {
@@ -1423,7 +1693,7 @@ func TestTransportChecksResponseHeaderListSize(t *testing.T) {
 	ct.run()
 	ct.run()
 }
 }
 
 
-// Test that the the Transport returns a typed error from Response.Body.Read calls
+// Test that the Transport returns a typed error from Response.Body.Read calls
 // when the server sends an error. (here we use a panic, since that should generate
 // when the server sends an error. (here we use a panic, since that should generate
 // a stream error, but others like cancel should be similar)
 // a stream error, but others like cancel should be similar)
 func TestTransportBodyReadErrorType(t *testing.T) {
 func TestTransportBodyReadErrorType(t *testing.T) {
@@ -2021,6 +2291,65 @@ func TestTransportReadHeadResponse(t *testing.T) {
 	ct.run()
 	ct.run()
 }
 }
 
 
+func TestTransportReadHeadResponseWithBody(t *testing.T) {
+	// This test use not valid response format.
+	// Discarding logger output to not spam tests output.
+	log.SetOutput(ioutil.Discard)
+	defer log.SetOutput(os.Stderr)
+
+	response := "redirecting to /elsewhere"
+	ct := newClientTester(t)
+	clientDone := make(chan struct{})
+	ct.client = func() error {
+		defer close(clientDone)
+		req, _ := http.NewRequest("HEAD", "https://dummy.tld/", nil)
+		res, err := ct.tr.RoundTrip(req)
+		if err != nil {
+			return err
+		}
+		if res.ContentLength != int64(len(response)) {
+			return fmt.Errorf("Content-Length = %d; want %d", res.ContentLength, len(response))
+		}
+		slurp, err := ioutil.ReadAll(res.Body)
+		if err != nil {
+			return fmt.Errorf("ReadAll: %v", err)
+		}
+		if len(slurp) > 0 {
+			return fmt.Errorf("Unexpected non-empty ReadAll body: %q", slurp)
+		}
+		return nil
+	}
+	ct.server = func() error {
+		ct.greet()
+		for {
+			f, err := ct.fr.ReadFrame()
+			if err != nil {
+				t.Logf("ReadFrame: %v", err)
+				return nil
+			}
+			hf, ok := f.(*HeadersFrame)
+			if !ok {
+				continue
+			}
+			var buf bytes.Buffer
+			enc := hpack.NewEncoder(&buf)
+			enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
+			enc.WriteField(hpack.HeaderField{Name: "content-length", Value: strconv.Itoa(len(response))})
+			ct.fr.WriteHeaders(HeadersFrameParam{
+				StreamID:      hf.StreamID,
+				EndHeaders:    true,
+				EndStream:     false,
+				BlockFragment: buf.Bytes(),
+			})
+			ct.fr.WriteData(hf.StreamID, true, []byte(response))
+
+			<-clientDone
+			return nil
+		}
+	}
+	ct.run()
+}
+
 type neverEnding byte
 type neverEnding byte
 
 
 func (b neverEnding) Read(p []byte) (int, error) {
 func (b neverEnding) Read(p []byte) (int, error) {
@@ -2205,12 +2534,11 @@ func testTransportUsesGoAwayDebugError(t *testing.T, failMidBody bool) {
 	ct.run()
 	ct.run()
 }
 }
 
 
-// See golang.org/issue/16481
-func TestTransportReturnsUnusedFlowControl(t *testing.T) {
+func testTransportReturnsUnusedFlowControl(t *testing.T, oneDataFrame bool) {
 	ct := newClientTester(t)
 	ct := newClientTester(t)
 
 
-	clientClosed := make(chan bool, 1)
-	serverWroteBody := make(chan bool, 1)
+	clientClosed := make(chan struct{})
+	serverWroteFirstByte := make(chan struct{})
 
 
 	ct.client = func() error {
 	ct.client = func() error {
 		req, _ := http.NewRequest("GET", "https://dummy.tld/", nil)
 		req, _ := http.NewRequest("GET", "https://dummy.tld/", nil)
@@ -2218,13 +2546,13 @@ func TestTransportReturnsUnusedFlowControl(t *testing.T) {
 		if err != nil {
 		if err != nil {
 			return err
 			return err
 		}
 		}
-		<-serverWroteBody
+		<-serverWroteFirstByte
 
 
 		if n, err := res.Body.Read(make([]byte, 1)); err != nil || n != 1 {
 		if n, err := res.Body.Read(make([]byte, 1)); err != nil || n != 1 {
 			return fmt.Errorf("body read = %v, %v; want 1, nil", n, err)
 			return fmt.Errorf("body read = %v, %v; want 1, nil", n, err)
 		}
 		}
 		res.Body.Close() // leaving 4999 bytes unread
 		res.Body.Close() // leaving 4999 bytes unread
-		clientClosed <- true
+		close(clientClosed)
 
 
 		return nil
 		return nil
 	}
 	}
@@ -2259,10 +2587,27 @@ func TestTransportReturnsUnusedFlowControl(t *testing.T) {
 			EndStream:     false,
 			EndStream:     false,
 			BlockFragment: buf.Bytes(),
 			BlockFragment: buf.Bytes(),
 		})
 		})
-		ct.fr.WriteData(hf.StreamID, false, make([]byte, 5000)) // without ending stream
-		serverWroteBody <- true
 
 
-		<-clientClosed
+		// Two cases:
+		// - Send one DATA frame with 5000 bytes.
+		// - Send two DATA frames with 1 and 4999 bytes each.
+		//
+		// In both cases, the client should consume one byte of data,
+		// refund that byte, then refund the following 4999 bytes.
+		//
+		// In the second case, the server waits for the client connection to
+		// close before seconding the second DATA frame. This tests the case
+		// where the client receives a DATA frame after it has reset the stream.
+		if oneDataFrame {
+			ct.fr.WriteData(hf.StreamID, false /* don't end stream */, make([]byte, 5000))
+			close(serverWroteFirstByte)
+			<-clientClosed
+		} else {
+			ct.fr.WriteData(hf.StreamID, false /* don't end stream */, make([]byte, 1))
+			close(serverWroteFirstByte)
+			<-clientClosed
+			ct.fr.WriteData(hf.StreamID, false /* don't end stream */, make([]byte, 4999))
+		}
 
 
 		waitingFor := "RSTStreamFrame"
 		waitingFor := "RSTStreamFrame"
 		for {
 		for {
@@ -2276,7 +2621,7 @@ func TestTransportReturnsUnusedFlowControl(t *testing.T) {
 			switch waitingFor {
 			switch waitingFor {
 			case "RSTStreamFrame":
 			case "RSTStreamFrame":
 				if rf, ok := f.(*RSTStreamFrame); !ok || rf.ErrCode != ErrCodeCancel {
 				if rf, ok := f.(*RSTStreamFrame); !ok || rf.ErrCode != ErrCodeCancel {
-					return fmt.Errorf("Expected a WindowUpdateFrame with code cancel; got %v", summarizeFrame(f))
+					return fmt.Errorf("Expected a RSTStreamFrame with code cancel; got %v", summarizeFrame(f))
 				}
 				}
 				waitingFor = "WindowUpdateFrame"
 				waitingFor = "WindowUpdateFrame"
 			case "WindowUpdateFrame":
 			case "WindowUpdateFrame":
@@ -2290,6 +2635,16 @@ func TestTransportReturnsUnusedFlowControl(t *testing.T) {
 	ct.run()
 	ct.run()
 }
 }
 
 
+// See golang.org/issue/16481
+func TestTransportReturnsUnusedFlowControlSingleWrite(t *testing.T) {
+	testTransportReturnsUnusedFlowControl(t, true)
+}
+
+// See golang.org/issue/20469
+func TestTransportReturnsUnusedFlowControlMultipleWrites(t *testing.T) {
+	testTransportReturnsUnusedFlowControl(t, false)
+}
+
 // Issue 16612: adjust flow control on open streams when transport
 // Issue 16612: adjust flow control on open streams when transport
 // receives SETTINGS with INITIAL_WINDOW_SIZE from server.
 // receives SETTINGS with INITIAL_WINDOW_SIZE from server.
 func TestTransportAdjustsFlowControl(t *testing.T) {
 func TestTransportAdjustsFlowControl(t *testing.T) {
@@ -2529,7 +2884,7 @@ func TestTransportBodyDoubleEndStream(t *testing.T) {
 	}
 	}
 }
 }
 
 
-// golangorg/issue/16847
+// golang.org/issue/16847, golang.org/issue/19103
 func TestTransportRequestPathPseudo(t *testing.T) {
 func TestTransportRequestPathPseudo(t *testing.T) {
 	type result struct {
 	type result struct {
 		path string
 		path string
@@ -2549,9 +2904,9 @@ func TestTransportRequestPathPseudo(t *testing.T) {
 			},
 			},
 			want: result{path: "/foo"},
 			want: result{path: "/foo"},
 		},
 		},
-		// I guess we just don't let users request "//foo" as
-		// a path, since it's illegal to start with two
-		// slashes....
+		// In Go 1.7, we accepted paths of "//foo".
+		// In Go 1.8, we rejected it (issue 16847).
+		// In Go 1.9, we accepted it again (issue 19103).
 		1: {
 		1: {
 			req: &http.Request{
 			req: &http.Request{
 				Method: "GET",
 				Method: "GET",
@@ -2560,7 +2915,7 @@ func TestTransportRequestPathPseudo(t *testing.T) {
 					Path: "//foo",
 					Path: "//foo",
 				},
 				},
 			},
 			},
-			want: result{err: `invalid request :path "//foo"`},
+			want: result{path: "//foo"},
 		},
 		},
 
 
 		// Opaque with //$Matching_Hostname/path
 		// Opaque with //$Matching_Hostname/path
@@ -2631,7 +2986,7 @@ func TestTransportRequestPathPseudo(t *testing.T) {
 		},
 		},
 	}
 	}
 	for i, tt := range tests {
 	for i, tt := range tests {
-		cc := &ClientConn{}
+		cc := &ClientConn{peerMaxHeaderListSize: 0xffffffffffffffff}
 		cc.henc = hpack.NewEncoder(&cc.hbuf)
 		cc.henc = hpack.NewEncoder(&cc.hbuf)
 		cc.mu.Lock()
 		cc.mu.Lock()
 		hdrs, err := cc.encodeHeaders(tt.req, false, "", -1)
 		hdrs, err := cc.encodeHeaders(tt.req, false, "", -1)
@@ -2748,6 +3103,34 @@ func TestTransportCancelDataResponseRace(t *testing.T) {
 	}
 	}
 }
 }
 
 
+// Issue 21316: It should be safe to reuse an http.Request after the
+// request has completed.
+func TestTransportNoRaceOnRequestObjectAfterRequestComplete(t *testing.T) {
+	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+		w.WriteHeader(200)
+		io.WriteString(w, "body")
+	}, optOnlyServer)
+	defer st.Close()
+
+	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
+	defer tr.CloseIdleConnections()
+
+	req, _ := http.NewRequest("GET", st.ts.URL, nil)
+	resp, err := tr.RoundTrip(req)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if _, err = io.Copy(ioutil.Discard, resp.Body); err != nil {
+		t.Fatalf("error reading response body: %v", err)
+	}
+	if err := resp.Body.Close(); err != nil {
+		t.Fatalf("error closing response body: %v", err)
+	}
+
+	// This access of req.Header should not race with code in the transport.
+	req.Header = http.Header{}
+}
+
 func TestTransportRetryAfterGOAWAY(t *testing.T) {
 func TestTransportRetryAfterGOAWAY(t *testing.T) {
 	var dialer struct {
 	var dialer struct {
 		sync.Mutex
 		sync.Mutex
@@ -2895,6 +3278,344 @@ func TestTransportRetryAfterGOAWAY(t *testing.T) {
 	}
 	}
 }
 }
 
 
+func TestTransportRetryAfterRefusedStream(t *testing.T) {
+	clientDone := make(chan struct{})
+	ct := newClientTester(t)
+	ct.client = func() error {
+		defer ct.cc.(*net.TCPConn).CloseWrite()
+		defer close(clientDone)
+		req, _ := http.NewRequest("GET", "https://dummy.tld/", nil)
+		resp, err := ct.tr.RoundTrip(req)
+		if err != nil {
+			return fmt.Errorf("RoundTrip: %v", err)
+		}
+		resp.Body.Close()
+		if resp.StatusCode != 204 {
+			return fmt.Errorf("Status = %v; want 204", resp.StatusCode)
+		}
+		return nil
+	}
+	ct.server = func() error {
+		ct.greet()
+		var buf bytes.Buffer
+		enc := hpack.NewEncoder(&buf)
+		nreq := 0
+
+		for {
+			f, err := ct.fr.ReadFrame()
+			if err != nil {
+				select {
+				case <-clientDone:
+					// If the client's done, it
+					// will have reported any
+					// errors on its side.
+					return nil
+				default:
+					return err
+				}
+			}
+			switch f := f.(type) {
+			case *WindowUpdateFrame, *SettingsFrame:
+			case *HeadersFrame:
+				if !f.HeadersEnded() {
+					return fmt.Errorf("headers should have END_HEADERS be ended: %v", f)
+				}
+				nreq++
+				if nreq == 1 {
+					ct.fr.WriteRSTStream(f.StreamID, ErrCodeRefusedStream)
+				} else {
+					enc.WriteField(hpack.HeaderField{Name: ":status", Value: "204"})
+					ct.fr.WriteHeaders(HeadersFrameParam{
+						StreamID:      f.StreamID,
+						EndHeaders:    true,
+						EndStream:     true,
+						BlockFragment: buf.Bytes(),
+					})
+				}
+			default:
+				return fmt.Errorf("Unexpected client frame %v", f)
+			}
+		}
+	}
+	ct.run()
+}
+
+func TestTransportRetryHasLimit(t *testing.T) {
+	// Skip in short mode because the total expected delay is 1s+2s+4s+8s+16s=29s.
+	if testing.Short() {
+		t.Skip("skipping long test in short mode")
+	}
+	clientDone := make(chan struct{})
+	ct := newClientTester(t)
+	ct.client = func() error {
+		defer ct.cc.(*net.TCPConn).CloseWrite()
+		defer close(clientDone)
+		req, _ := http.NewRequest("GET", "https://dummy.tld/", nil)
+		resp, err := ct.tr.RoundTrip(req)
+		if err == nil {
+			return fmt.Errorf("RoundTrip expected error, got response: %+v", resp)
+		}
+		t.Logf("expected error, got: %v", err)
+		return nil
+	}
+	ct.server = func() error {
+		ct.greet()
+		for {
+			f, err := ct.fr.ReadFrame()
+			if err != nil {
+				select {
+				case <-clientDone:
+					// If the client's done, it
+					// will have reported any
+					// errors on its side.
+					return nil
+				default:
+					return err
+				}
+			}
+			switch f := f.(type) {
+			case *WindowUpdateFrame, *SettingsFrame:
+			case *HeadersFrame:
+				if !f.HeadersEnded() {
+					return fmt.Errorf("headers should have END_HEADERS be ended: %v", f)
+				}
+				ct.fr.WriteRSTStream(f.StreamID, ErrCodeRefusedStream)
+			default:
+				return fmt.Errorf("Unexpected client frame %v", f)
+			}
+		}
+	}
+	ct.run()
+}
+
+func TestTransportResponseDataBeforeHeaders(t *testing.T) {
+	// This test use not valid response format.
+	// Discarding logger output to not spam tests output.
+	log.SetOutput(ioutil.Discard)
+	defer log.SetOutput(os.Stderr)
+
+	ct := newClientTester(t)
+	ct.client = func() error {
+		defer ct.cc.(*net.TCPConn).CloseWrite()
+		req := httptest.NewRequest("GET", "https://dummy.tld/", nil)
+		// First request is normal to ensure the check is per stream and not per connection.
+		_, err := ct.tr.RoundTrip(req)
+		if err != nil {
+			return fmt.Errorf("RoundTrip expected no error, got: %v", err)
+		}
+		// Second request returns a DATA frame with no HEADERS.
+		resp, err := ct.tr.RoundTrip(req)
+		if err == nil {
+			return fmt.Errorf("RoundTrip expected error, got response: %+v", resp)
+		}
+		if err, ok := err.(StreamError); !ok || err.Code != ErrCodeProtocol {
+			return fmt.Errorf("expected stream PROTOCOL_ERROR, got: %v", err)
+		}
+		return nil
+	}
+	ct.server = func() error {
+		ct.greet()
+		for {
+			f, err := ct.fr.ReadFrame()
+			if err == io.EOF {
+				return nil
+			} else if err != nil {
+				return err
+			}
+			switch f := f.(type) {
+			case *WindowUpdateFrame, *SettingsFrame:
+			case *HeadersFrame:
+				switch f.StreamID {
+				case 1:
+					// Send a valid response to first request.
+					var buf bytes.Buffer
+					enc := hpack.NewEncoder(&buf)
+					enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
+					ct.fr.WriteHeaders(HeadersFrameParam{
+						StreamID:      f.StreamID,
+						EndHeaders:    true,
+						EndStream:     true,
+						BlockFragment: buf.Bytes(),
+					})
+				case 3:
+					ct.fr.WriteData(f.StreamID, true, []byte("payload"))
+				}
+			default:
+				return fmt.Errorf("Unexpected client frame %v", f)
+			}
+		}
+	}
+	ct.run()
+}
+func TestTransportRequestsStallAtServerLimit(t *testing.T) {
+	const maxConcurrent = 2
+
+	greet := make(chan struct{})      // server sends initial SETTINGS frame
+	gotRequest := make(chan struct{}) // server received a request
+	clientDone := make(chan struct{})
+
+	// Collect errors from goroutines.
+	var wg sync.WaitGroup
+	errs := make(chan error, 100)
+	defer func() {
+		wg.Wait()
+		close(errs)
+		for err := range errs {
+			t.Error(err)
+		}
+	}()
+
+	// We will send maxConcurrent+2 requests. This checker goroutine waits for the
+	// following stages:
+	//   1. The first maxConcurrent requests are received by the server.
+	//   2. The client will cancel the next request
+	//   3. The server is unblocked so it can service the first maxConcurrent requests
+	//   4. The client will send the final request
+	wg.Add(1)
+	unblockClient := make(chan struct{})
+	clientRequestCancelled := make(chan struct{})
+	unblockServer := make(chan struct{})
+	go func() {
+		defer wg.Done()
+		// Stage 1.
+		for k := 0; k < maxConcurrent; k++ {
+			<-gotRequest
+		}
+		// Stage 2.
+		close(unblockClient)
+		<-clientRequestCancelled
+		// Stage 3: give some time for the final RoundTrip call to be scheduled and
+		// verify that the final request is not sent.
+		time.Sleep(50 * time.Millisecond)
+		select {
+		case <-gotRequest:
+			errs <- errors.New("last request did not stall")
+			close(unblockServer)
+			return
+		default:
+		}
+		close(unblockServer)
+		// Stage 4.
+		<-gotRequest
+	}()
+
+	ct := newClientTester(t)
+	ct.client = func() error {
+		var wg sync.WaitGroup
+		defer func() {
+			wg.Wait()
+			close(clientDone)
+			ct.cc.(*net.TCPConn).CloseWrite()
+		}()
+		for k := 0; k < maxConcurrent+2; k++ {
+			wg.Add(1)
+			go func(k int) {
+				defer wg.Done()
+				// Don't send the second request until after receiving SETTINGS from the server
+				// to avoid a race where we use the default SettingMaxConcurrentStreams, which
+				// is much larger than maxConcurrent. We have to send the first request before
+				// waiting because the first request triggers the dial and greet.
+				if k > 0 {
+					<-greet
+				}
+				// Block until maxConcurrent requests are sent before sending any more.
+				if k >= maxConcurrent {
+					<-unblockClient
+				}
+				req, _ := http.NewRequest("GET", fmt.Sprintf("https://dummy.tld/%d", k), nil)
+				if k == maxConcurrent {
+					// This request will be canceled.
+					cancel := make(chan struct{})
+					req.Cancel = cancel
+					close(cancel)
+					_, err := ct.tr.RoundTrip(req)
+					close(clientRequestCancelled)
+					if err == nil {
+						errs <- fmt.Errorf("RoundTrip(%d) should have failed due to cancel", k)
+						return
+					}
+				} else {
+					resp, err := ct.tr.RoundTrip(req)
+					if err != nil {
+						errs <- fmt.Errorf("RoundTrip(%d): %v", k, err)
+						return
+					}
+					ioutil.ReadAll(resp.Body)
+					resp.Body.Close()
+					if resp.StatusCode != 204 {
+						errs <- fmt.Errorf("Status = %v; want 204", resp.StatusCode)
+						return
+					}
+				}
+			}(k)
+		}
+		return nil
+	}
+
+	ct.server = func() error {
+		var wg sync.WaitGroup
+		defer wg.Wait()
+
+		ct.greet(Setting{SettingMaxConcurrentStreams, maxConcurrent})
+
+		// Server write loop.
+		var buf bytes.Buffer
+		enc := hpack.NewEncoder(&buf)
+		writeResp := make(chan uint32, maxConcurrent+1)
+
+		wg.Add(1)
+		go func() {
+			defer wg.Done()
+			<-unblockServer
+			for id := range writeResp {
+				buf.Reset()
+				enc.WriteField(hpack.HeaderField{Name: ":status", Value: "204"})
+				ct.fr.WriteHeaders(HeadersFrameParam{
+					StreamID:      id,
+					EndHeaders:    true,
+					EndStream:     true,
+					BlockFragment: buf.Bytes(),
+				})
+			}
+		}()
+
+		// Server read loop.
+		var nreq int
+		for {
+			f, err := ct.fr.ReadFrame()
+			if err != nil {
+				select {
+				case <-clientDone:
+					// If the client's done, it will have reported any errors on its side.
+					return nil
+				default:
+					return err
+				}
+			}
+			switch f := f.(type) {
+			case *WindowUpdateFrame:
+			case *SettingsFrame:
+				// Wait for the client SETTINGS ack until ending the greet.
+				close(greet)
+			case *HeadersFrame:
+				if !f.HeadersEnded() {
+					return fmt.Errorf("headers should have END_HEADERS be ended: %v", f)
+				}
+				gotRequest <- struct{}{}
+				nreq++
+				writeResp <- f.StreamID
+				if nreq == maxConcurrent+1 {
+					close(writeResp)
+				}
+			default:
+				return fmt.Errorf("Unexpected client frame %v", f)
+			}
+		}
+	}
+
+	ct.run()
+}
+
 func TestAuthorityAddr(t *testing.T) {
 func TestAuthorityAddr(t *testing.T) {
 	tests := []struct {
 	tests := []struct {
 		scheme, authority string
 		scheme, authority string
@@ -2969,3 +3690,158 @@ func TestTransportAllocationsAfterResponseBodyClose(t *testing.T) {
 		t.Errorf("Handler Write err = %v; want errStreamClosed", gotErr)
 		t.Errorf("Handler Write err = %v; want errStreamClosed", gotErr)
 	}
 	}
 }
 }
+
+// Issue 18891: make sure Request.Body == NoBody means no DATA frame
+// is ever sent, even if empty.
+func TestTransportNoBodyMeansNoDATA(t *testing.T) {
+	ct := newClientTester(t)
+
+	unblockClient := make(chan bool)
+
+	ct.client = func() error {
+		req, _ := http.NewRequest("GET", "https://dummy.tld/", go18httpNoBody())
+		ct.tr.RoundTrip(req)
+		<-unblockClient
+		return nil
+	}
+	ct.server = func() error {
+		defer close(unblockClient)
+		defer ct.cc.(*net.TCPConn).Close()
+		ct.greet()
+
+		for {
+			f, err := ct.fr.ReadFrame()
+			if err != nil {
+				return fmt.Errorf("ReadFrame while waiting for Headers: %v", err)
+			}
+			switch f := f.(type) {
+			default:
+				return fmt.Errorf("Got %T; want HeadersFrame", f)
+			case *WindowUpdateFrame, *SettingsFrame:
+				continue
+			case *HeadersFrame:
+				if !f.StreamEnded() {
+					return fmt.Errorf("got headers frame without END_STREAM")
+				}
+				return nil
+			}
+		}
+	}
+	ct.run()
+}
+
+func benchSimpleRoundTrip(b *testing.B, nHeaders int) {
+	defer disableGoroutineTracking()()
+	b.ReportAllocs()
+	st := newServerTester(b,
+		func(w http.ResponseWriter, r *http.Request) {
+		},
+		optOnlyServer,
+		optQuiet,
+	)
+	defer st.Close()
+
+	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
+	defer tr.CloseIdleConnections()
+
+	req, err := http.NewRequest("GET", st.ts.URL, nil)
+	if err != nil {
+		b.Fatal(err)
+	}
+
+	for i := 0; i < nHeaders; i++ {
+		name := fmt.Sprint("A-", i)
+		req.Header.Set(name, "*")
+	}
+
+	b.ResetTimer()
+
+	for i := 0; i < b.N; i++ {
+		res, err := tr.RoundTrip(req)
+		if err != nil {
+			if res != nil {
+				res.Body.Close()
+			}
+			b.Fatalf("RoundTrip err = %v; want nil", err)
+		}
+		res.Body.Close()
+		if res.StatusCode != http.StatusOK {
+			b.Fatalf("Response code = %v; want %v", res.StatusCode, http.StatusOK)
+		}
+	}
+}
+
+type infiniteReader struct{}
+
+func (r infiniteReader) Read(b []byte) (int, error) {
+	return len(b), nil
+}
+
+// Issue 20521: it is not an error to receive a response and end stream
+// from the server without the body being consumed.
+func TestTransportResponseAndResetWithoutConsumingBodyRace(t *testing.T) {
+	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+		w.WriteHeader(http.StatusOK)
+	}, optOnlyServer)
+	defer st.Close()
+
+	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
+	defer tr.CloseIdleConnections()
+
+	// The request body needs to be big enough to trigger flow control.
+	req, _ := http.NewRequest("PUT", st.ts.URL, infiniteReader{})
+	res, err := tr.RoundTrip(req)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if res.StatusCode != http.StatusOK {
+		t.Fatalf("Response code = %v; want %v", res.StatusCode, http.StatusOK)
+	}
+}
+
+// Verify transport doesn't crash when receiving bogus response lacking a :status header.
+// Issue 22880.
+func TestTransportHandlesInvalidStatuslessResponse(t *testing.T) {
+	ct := newClientTester(t)
+	ct.client = func() error {
+		req, _ := http.NewRequest("GET", "https://dummy.tld/", nil)
+		_, err := ct.tr.RoundTrip(req)
+		const substr = "malformed response from server: missing status pseudo header"
+		if !strings.Contains(fmt.Sprint(err), substr) {
+			return fmt.Errorf("RoundTrip error = %v; want substring %q", err, substr)
+		}
+		return nil
+	}
+	ct.server = func() error {
+		ct.greet()
+		var buf bytes.Buffer
+		enc := hpack.NewEncoder(&buf)
+
+		for {
+			f, err := ct.fr.ReadFrame()
+			if err != nil {
+				return err
+			}
+			switch f := f.(type) {
+			case *HeadersFrame:
+				enc.WriteField(hpack.HeaderField{Name: "content-type", Value: "text/html"}) // no :status header
+				ct.fr.WriteHeaders(HeadersFrameParam{
+					StreamID:      f.StreamID,
+					EndHeaders:    true,
+					EndStream:     false, // we'll send some DATA to try to crash the transport
+					BlockFragment: buf.Bytes(),
+				})
+				ct.fr.WriteData(f.StreamID, true, []byte("payload"))
+				return nil
+			}
+		}
+	}
+	ct.run()
+}
+
+func BenchmarkClientRequestHeaders(b *testing.B) {
+	b.Run("   0 Headers", func(b *testing.B) { benchSimpleRoundTrip(b, 0) })
+	b.Run("  10 Headers", func(b *testing.B) { benchSimpleRoundTrip(b, 10) })
+	b.Run(" 100 Headers", func(b *testing.B) { benchSimpleRoundTrip(b, 100) })
+	b.Run("1000 Headers", func(b *testing.B) { benchSimpleRoundTrip(b, 1000) })
+}

+ 1 - 6
vendor/golang.org/x/net/http2/write.go

@@ -10,7 +10,6 @@ import (
 	"log"
 	"log"
 	"net/http"
 	"net/http"
 	"net/url"
 	"net/url"
-	"time"
 
 
 	"golang.org/x/net/http2/hpack"
 	"golang.org/x/net/http2/hpack"
 	"golang.org/x/net/lex/httplex"
 	"golang.org/x/net/lex/httplex"
@@ -90,11 +89,7 @@ type writeGoAway struct {
 
 
 func (p *writeGoAway) writeFrame(ctx writeContext) error {
 func (p *writeGoAway) writeFrame(ctx writeContext) error {
 	err := ctx.Framer().WriteGoAway(p.maxStreamID, p.code, nil)
 	err := ctx.Framer().WriteGoAway(p.maxStreamID, p.code, nil)
-	if p.code != 0 {
-		ctx.Flush() // ignore error: we're hanging up on them anyway
-		time.Sleep(50 * time.Millisecond)
-		ctx.CloseConn()
-	}
+	ctx.Flush() // ignore error: we're hanging up on them anyway
 	return err
 	return err
 }
 }
 
 

+ 274 - 0
vendor/golang.org/x/net/icmp/diag_test.go

@@ -0,0 +1,274 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package icmp_test
+
+import (
+	"errors"
+	"fmt"
+	"net"
+	"os"
+	"runtime"
+	"sync"
+	"testing"
+	"time"
+
+	"golang.org/x/net/icmp"
+	"golang.org/x/net/internal/iana"
+	"golang.org/x/net/internal/nettest"
+	"golang.org/x/net/ipv4"
+	"golang.org/x/net/ipv6"
+)
+
+type diagTest struct {
+	network, address string
+	protocol         int
+	m                icmp.Message
+}
+
+func TestDiag(t *testing.T) {
+	if testing.Short() {
+		t.Skip("avoid external network")
+	}
+
+	t.Run("Ping/NonPrivileged", func(t *testing.T) {
+		switch runtime.GOOS {
+		case "darwin":
+		case "linux":
+			t.Log("you may need to adjust the net.ipv4.ping_group_range kernel state")
+		default:
+			t.Logf("not supported on %s", runtime.GOOS)
+			return
+		}
+		for i, dt := range []diagTest{
+			{
+				"udp4", "0.0.0.0", iana.ProtocolICMP,
+				icmp.Message{
+					Type: ipv4.ICMPTypeEcho, Code: 0,
+					Body: &icmp.Echo{
+						ID:   os.Getpid() & 0xffff,
+						Data: []byte("HELLO-R-U-THERE"),
+					},
+				},
+			},
+
+			{
+				"udp6", "::", iana.ProtocolIPv6ICMP,
+				icmp.Message{
+					Type: ipv6.ICMPTypeEchoRequest, Code: 0,
+					Body: &icmp.Echo{
+						ID:   os.Getpid() & 0xffff,
+						Data: []byte("HELLO-R-U-THERE"),
+					},
+				},
+			},
+		} {
+			if err := doDiag(dt, i); err != nil {
+				t.Error(err)
+			}
+		}
+	})
+	t.Run("Ping/Privileged", func(t *testing.T) {
+		if m, ok := nettest.SupportsRawIPSocket(); !ok {
+			t.Skip(m)
+		}
+		for i, dt := range []diagTest{
+			{
+				"ip4:icmp", "0.0.0.0", iana.ProtocolICMP,
+				icmp.Message{
+					Type: ipv4.ICMPTypeEcho, Code: 0,
+					Body: &icmp.Echo{
+						ID:   os.Getpid() & 0xffff,
+						Data: []byte("HELLO-R-U-THERE"),
+					},
+				},
+			},
+
+			{
+				"ip6:ipv6-icmp", "::", iana.ProtocolIPv6ICMP,
+				icmp.Message{
+					Type: ipv6.ICMPTypeEchoRequest, Code: 0,
+					Body: &icmp.Echo{
+						ID:   os.Getpid() & 0xffff,
+						Data: []byte("HELLO-R-U-THERE"),
+					},
+				},
+			},
+		} {
+			if err := doDiag(dt, i); err != nil {
+				t.Error(err)
+			}
+		}
+	})
+	t.Run("Probe/Privileged", func(t *testing.T) {
+		if m, ok := nettest.SupportsRawIPSocket(); !ok {
+			t.Skip(m)
+		}
+		for i, dt := range []diagTest{
+			{
+				"ip4:icmp", "0.0.0.0", iana.ProtocolICMP,
+				icmp.Message{
+					Type: ipv4.ICMPTypeExtendedEchoRequest, Code: 0,
+					Body: &icmp.ExtendedEchoRequest{
+						ID:    os.Getpid() & 0xffff,
+						Local: true,
+						Extensions: []icmp.Extension{
+							&icmp.InterfaceIdent{
+								Class: 3, Type: 1,
+								Name: "doesnotexist",
+							},
+						},
+					},
+				},
+			},
+
+			{
+				"ip6:ipv6-icmp", "::", iana.ProtocolIPv6ICMP,
+				icmp.Message{
+					Type: ipv6.ICMPTypeExtendedEchoRequest, Code: 0,
+					Body: &icmp.ExtendedEchoRequest{
+						ID:    os.Getpid() & 0xffff,
+						Local: true,
+						Extensions: []icmp.Extension{
+							&icmp.InterfaceIdent{
+								Class: 3, Type: 1,
+								Name: "doesnotexist",
+							},
+						},
+					},
+				},
+			},
+		} {
+			if err := doDiag(dt, i); err != nil {
+				t.Error(err)
+			}
+		}
+	})
+}
+
+func doDiag(dt diagTest, seq int) error {
+	c, err := icmp.ListenPacket(dt.network, dt.address)
+	if err != nil {
+		return err
+	}
+	defer c.Close()
+
+	dst, err := googleAddr(c, dt.protocol)
+	if err != nil {
+		return err
+	}
+
+	if dt.network != "udp6" && dt.protocol == iana.ProtocolIPv6ICMP {
+		var f ipv6.ICMPFilter
+		f.SetAll(true)
+		f.Accept(ipv6.ICMPTypeDestinationUnreachable)
+		f.Accept(ipv6.ICMPTypePacketTooBig)
+		f.Accept(ipv6.ICMPTypeTimeExceeded)
+		f.Accept(ipv6.ICMPTypeParameterProblem)
+		f.Accept(ipv6.ICMPTypeEchoReply)
+		f.Accept(ipv6.ICMPTypeExtendedEchoReply)
+		if err := c.IPv6PacketConn().SetICMPFilter(&f); err != nil {
+			return err
+		}
+	}
+
+	switch m := dt.m.Body.(type) {
+	case *icmp.Echo:
+		m.Seq = 1 << uint(seq)
+	case *icmp.ExtendedEchoRequest:
+		m.Seq = 1 << uint(seq)
+	}
+	wb, err := dt.m.Marshal(nil)
+	if err != nil {
+		return err
+	}
+	if n, err := c.WriteTo(wb, dst); err != nil {
+		return err
+	} else if n != len(wb) {
+		return fmt.Errorf("got %v; want %v", n, len(wb))
+	}
+
+	rb := make([]byte, 1500)
+	if err := c.SetReadDeadline(time.Now().Add(3 * time.Second)); err != nil {
+		return err
+	}
+	n, peer, err := c.ReadFrom(rb)
+	if err != nil {
+		return err
+	}
+	rm, err := icmp.ParseMessage(dt.protocol, rb[:n])
+	if err != nil {
+		return err
+	}
+	switch {
+	case dt.m.Type == ipv4.ICMPTypeEcho && rm.Type == ipv4.ICMPTypeEchoReply:
+		fallthrough
+	case dt.m.Type == ipv6.ICMPTypeEchoRequest && rm.Type == ipv6.ICMPTypeEchoReply:
+		fallthrough
+	case dt.m.Type == ipv4.ICMPTypeExtendedEchoRequest && rm.Type == ipv4.ICMPTypeExtendedEchoReply:
+		fallthrough
+	case dt.m.Type == ipv6.ICMPTypeExtendedEchoRequest && rm.Type == ipv6.ICMPTypeExtendedEchoReply:
+		return nil
+	default:
+		return fmt.Errorf("got %+v from %v; want echo reply or extended echo reply", rm, peer)
+	}
+}
+
+func googleAddr(c *icmp.PacketConn, protocol int) (net.Addr, error) {
+	host := "ipv4.google.com"
+	if protocol == iana.ProtocolIPv6ICMP {
+		host = "ipv6.google.com"
+	}
+	ips, err := net.LookupIP(host)
+	if err != nil {
+		return nil, err
+	}
+	netaddr := func(ip net.IP) (net.Addr, error) {
+		switch c.LocalAddr().(type) {
+		case *net.UDPAddr:
+			return &net.UDPAddr{IP: ip}, nil
+		case *net.IPAddr:
+			return &net.IPAddr{IP: ip}, nil
+		default:
+			return nil, errors.New("neither UDPAddr nor IPAddr")
+		}
+	}
+	if len(ips) > 0 {
+		return netaddr(ips[0])
+	}
+	return nil, errors.New("no A or AAAA record")
+}
+
+func TestConcurrentNonPrivilegedListenPacket(t *testing.T) {
+	if testing.Short() {
+		t.Skip("avoid external network")
+	}
+	switch runtime.GOOS {
+	case "darwin":
+	case "linux":
+		t.Log("you may need to adjust the net.ipv4.ping_group_range kernel state")
+	default:
+		t.Skipf("not supported on %s", runtime.GOOS)
+	}
+
+	network, address := "udp4", "127.0.0.1"
+	if !nettest.SupportsIPv4() {
+		network, address = "udp6", "::1"
+	}
+	const N = 1000
+	var wg sync.WaitGroup
+	wg.Add(N)
+	for i := 0; i < N; i++ {
+		go func() {
+			defer wg.Done()
+			c, err := icmp.ListenPacket(network, address)
+			if err != nil {
+				t.Error(err)
+				return
+			}
+			c.Close()
+		}()
+	}
+	wg.Wait()
+}

+ 4 - 4
vendor/golang.org/x/net/icmp/dstunreach.go

@@ -16,24 +16,24 @@ func (p *DstUnreach) Len(proto int) int {
 	if p == nil {
 	if p == nil {
 		return 0
 		return 0
 	}
 	}
-	l, _ := multipartMessageBodyDataLen(proto, p.Data, p.Extensions)
+	l, _ := multipartMessageBodyDataLen(proto, true, p.Data, p.Extensions)
 	return 4 + l
 	return 4 + l
 }
 }
 
 
 // Marshal implements the Marshal method of MessageBody interface.
 // Marshal implements the Marshal method of MessageBody interface.
 func (p *DstUnreach) Marshal(proto int) ([]byte, error) {
 func (p *DstUnreach) Marshal(proto int) ([]byte, error) {
-	return marshalMultipartMessageBody(proto, p.Data, p.Extensions)
+	return marshalMultipartMessageBody(proto, true, p.Data, p.Extensions)
 }
 }
 
 
 // parseDstUnreach parses b as an ICMP destination unreachable message
 // parseDstUnreach parses b as an ICMP destination unreachable message
 // body.
 // body.
-func parseDstUnreach(proto int, b []byte) (MessageBody, error) {
+func parseDstUnreach(proto int, typ Type, b []byte) (MessageBody, error) {
 	if len(b) < 4 {
 	if len(b) < 4 {
 		return nil, errMessageTooShort
 		return nil, errMessageTooShort
 	}
 	}
 	p := &DstUnreach{}
 	p := &DstUnreach{}
 	var err error
 	var err error
-	p.Data, p.Extensions, err = parseMultipartMessageBody(proto, b)
+	p.Data, p.Extensions, err = parseMultipartMessageBody(proto, typ, b)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}

+ 113 - 1
vendor/golang.org/x/net/icmp/echo.go

@@ -31,7 +31,7 @@ func (p *Echo) Marshal(proto int) ([]byte, error) {
 }
 }
 
 
 // parseEcho parses b as an ICMP echo request or reply message body.
 // parseEcho parses b as an ICMP echo request or reply message body.
-func parseEcho(proto int, b []byte) (MessageBody, error) {
+func parseEcho(proto int, _ Type, b []byte) (MessageBody, error) {
 	bodyLen := len(b)
 	bodyLen := len(b)
 	if bodyLen < 4 {
 	if bodyLen < 4 {
 		return nil, errMessageTooShort
 		return nil, errMessageTooShort
@@ -43,3 +43,115 @@ func parseEcho(proto int, b []byte) (MessageBody, error) {
 	}
 	}
 	return p, nil
 	return p, nil
 }
 }
+
+// An ExtendedEchoRequest represents an ICMP extended echo request
+// message body.
+type ExtendedEchoRequest struct {
+	ID         int         // identifier
+	Seq        int         // sequence number
+	Local      bool        // must be true when identifying by name or index
+	Extensions []Extension // extensions
+}
+
+// Len implements the Len method of MessageBody interface.
+func (p *ExtendedEchoRequest) Len(proto int) int {
+	if p == nil {
+		return 0
+	}
+	l, _ := multipartMessageBodyDataLen(proto, false, nil, p.Extensions)
+	return 4 + l
+}
+
+// Marshal implements the Marshal method of MessageBody interface.
+func (p *ExtendedEchoRequest) Marshal(proto int) ([]byte, error) {
+	b, err := marshalMultipartMessageBody(proto, false, nil, p.Extensions)
+	if err != nil {
+		return nil, err
+	}
+	bb := make([]byte, 4)
+	binary.BigEndian.PutUint16(bb[:2], uint16(p.ID))
+	bb[2] = byte(p.Seq)
+	if p.Local {
+		bb[3] |= 0x01
+	}
+	bb = append(bb, b...)
+	return bb, nil
+}
+
+// parseExtendedEchoRequest parses b as an ICMP extended echo request
+// message body.
+func parseExtendedEchoRequest(proto int, typ Type, b []byte) (MessageBody, error) {
+	if len(b) < 4+4 {
+		return nil, errMessageTooShort
+	}
+	p := &ExtendedEchoRequest{ID: int(binary.BigEndian.Uint16(b[:2])), Seq: int(b[2])}
+	if b[3]&0x01 != 0 {
+		p.Local = true
+	}
+	var err error
+	_, p.Extensions, err = parseMultipartMessageBody(proto, typ, b[4:])
+	if err != nil {
+		return nil, err
+	}
+	return p, nil
+}
+
+// An ExtendedEchoReply represents an ICMP extended echo reply message
+// body.
+type ExtendedEchoReply struct {
+	ID     int  // identifier
+	Seq    int  // sequence number
+	State  int  // 3-bit state working together with Message.Code
+	Active bool // probed interface is active
+	IPv4   bool // probed interface runs IPv4
+	IPv6   bool // probed interface runs IPv6
+}
+
+// Len implements the Len method of MessageBody interface.
+func (p *ExtendedEchoReply) Len(proto int) int {
+	if p == nil {
+		return 0
+	}
+	return 4
+}
+
+// Marshal implements the Marshal method of MessageBody interface.
+func (p *ExtendedEchoReply) Marshal(proto int) ([]byte, error) {
+	b := make([]byte, 4)
+	binary.BigEndian.PutUint16(b[:2], uint16(p.ID))
+	b[2] = byte(p.Seq)
+	b[3] = byte(p.State<<5) & 0xe0
+	if p.Active {
+		b[3] |= 0x04
+	}
+	if p.IPv4 {
+		b[3] |= 0x02
+	}
+	if p.IPv6 {
+		b[3] |= 0x01
+	}
+	return b, nil
+}
+
+// parseExtendedEchoReply parses b as an ICMP extended echo reply
+// message body.
+func parseExtendedEchoReply(proto int, _ Type, b []byte) (MessageBody, error) {
+	if len(b) < 4 {
+		return nil, errMessageTooShort
+	}
+	p := &ExtendedEchoReply{
+		ID:    int(binary.BigEndian.Uint16(b[:2])),
+		Seq:   int(b[2]),
+		State: int(b[3]) >> 5,
+	}
+	if b[3]&0x04 != 0 {
+		p.Active = true
+	}
+	if b[3]&0x02 != 0 {
+		p.IPv4 = true
+	}
+	if b[3]&0x01 != 0 {
+		p.IPv6 = true
+	}
+	return p, nil
+}

+ 31 - 12
vendor/golang.org/x/net/icmp/extension.go

@@ -4,7 +4,12 @@
 
 
 package icmp
 package icmp
 
 
-import "encoding/binary"
+import (
+	"encoding/binary"
+
+	"golang.org/x/net/ipv4"
+	"golang.org/x/net/ipv6"
+)
 
 
 // An Extension represents an ICMP extension.
 // An Extension represents an ICMP extension.
 type Extension interface {
 type Extension interface {
@@ -38,7 +43,7 @@ func validExtensionHeader(b []byte) bool {
 // It will return a list of ICMP extensions and an adjusted length
 // It will return a list of ICMP extensions and an adjusted length
 // attribute that represents the length of the padded original
 // attribute that represents the length of the padded original
 // datagram field. Otherwise, it returns an error.
 // datagram field. Otherwise, it returns an error.
-func parseExtensions(b []byte, l int) ([]Extension, int, error) {
+func parseExtensions(typ Type, b []byte, l int) ([]Extension, int, error) {
 	// Still a lot of non-RFC 4884 compliant implementations are
 	// Still a lot of non-RFC 4884 compliant implementations are
 	// out there. Set the length attribute l to 128 when it looks
 	// out there. Set the length attribute l to 128 when it looks
 	// inappropriate for backwards compatibility.
 	// inappropriate for backwards compatibility.
@@ -48,20 +53,28 @@ func parseExtensions(b []byte, l int) ([]Extension, int, error) {
 	// header.
 	// header.
 	//
 	//
 	// See RFC 4884 for further information.
 	// See RFC 4884 for further information.
-	if 128 > l || l+8 > len(b) {
-		l = 128
-	}
-	if l+8 > len(b) {
-		return nil, -1, errNoExtension
-	}
-	if !validExtensionHeader(b[l:]) {
-		if l == 128 {
+	switch typ {
+	case ipv4.ICMPTypeExtendedEchoRequest, ipv6.ICMPTypeExtendedEchoRequest:
+		if len(b) < 8 || !validExtensionHeader(b) {
 			return nil, -1, errNoExtension
 			return nil, -1, errNoExtension
 		}
 		}
-		l = 128
-		if !validExtensionHeader(b[l:]) {
+		l = 0
+	default:
+		if 128 > l || l+8 > len(b) {
+			l = 128
+		}
+		if l+8 > len(b) {
 			return nil, -1, errNoExtension
 			return nil, -1, errNoExtension
 		}
 		}
+		if !validExtensionHeader(b[l:]) {
+			if l == 128 {
+				return nil, -1, errNoExtension
+			}
+			l = 128
+			if !validExtensionHeader(b[l:]) {
+				return nil, -1, errNoExtension
+			}
+		}
 	}
 	}
 	var exts []Extension
 	var exts []Extension
 	for b = b[l+4:]; len(b) >= 4; {
 	for b = b[l+4:]; len(b) >= 4; {
@@ -82,6 +95,12 @@ func parseExtensions(b []byte, l int) ([]Extension, int, error) {
 				return nil, -1, err
 				return nil, -1, err
 			}
 			}
 			exts = append(exts, ext)
 			exts = append(exts, ext)
+		case classInterfaceIdent:
+			ext, err := parseInterfaceIdent(b[:ol])
+			if err != nil {
+				return nil, -1, err
+			}
+			exts = append(exts, ext)
 		}
 		}
 		b = b[ol:]
 		b = b[ol:]
 	}
 	}

+ 291 - 217
vendor/golang.org/x/net/icmp/extension_test.go

@@ -5,253 +5,327 @@
 package icmp
 package icmp
 
 
 import (
 import (
+	"fmt"
 	"net"
 	"net"
 	"reflect"
 	"reflect"
 	"testing"
 	"testing"
 
 
 	"golang.org/x/net/internal/iana"
 	"golang.org/x/net/internal/iana"
+	"golang.org/x/net/ipv4"
+	"golang.org/x/net/ipv6"
 )
 )
 
 
-var marshalAndParseExtensionTests = []struct {
-	proto int
-	hdr   []byte
-	obj   []byte
-	exts  []Extension
-}{
-	// MPLS label stack with no label
-	{
-		proto: iana.ProtocolICMP,
-		hdr: []byte{
-			0x20, 0x00, 0x00, 0x00,
-		},
-		obj: []byte{
-			0x00, 0x04, 0x01, 0x01,
-		},
-		exts: []Extension{
-			&MPLSLabelStack{
-				Class: classMPLSLabelStack,
-				Type:  typeIncomingMPLSLabelStack,
+func TestMarshalAndParseExtension(t *testing.T) {
+	fn := func(t *testing.T, proto int, typ Type, hdr, obj []byte, te Extension) error {
+		b, err := te.Marshal(proto)
+		if err != nil {
+			return err
+		}
+		if !reflect.DeepEqual(b, obj) {
+			return fmt.Errorf("got %#v; want %#v", b, obj)
+		}
+		switch typ {
+		case ipv4.ICMPTypeExtendedEchoRequest, ipv6.ICMPTypeExtendedEchoRequest:
+			exts, l, err := parseExtensions(typ, append(hdr, obj...), 0)
+			if err != nil {
+				return err
+			}
+			if l != 0 {
+				return fmt.Errorf("got %d; want 0", l)
+			}
+			if !reflect.DeepEqual(exts, []Extension{te}) {
+				return fmt.Errorf("got %#v; want %#v", exts[0], te)
+			}
+		default:
+			for i, wire := range []struct {
+				data     []byte // original datagram
+				inlattr  int    // length of padded original datagram, a hint
+				outlattr int    // length of padded original datagram, a want
+				err      error
+			}{
+				{nil, 0, -1, errNoExtension},
+				{make([]byte, 127), 128, -1, errNoExtension},
+
+				{make([]byte, 128), 127, -1, errNoExtension},
+				{make([]byte, 128), 128, -1, errNoExtension},
+				{make([]byte, 128), 129, -1, errNoExtension},
+
+				{append(make([]byte, 128), append(hdr, obj...)...), 127, 128, nil},
+				{append(make([]byte, 128), append(hdr, obj...)...), 128, 128, nil},
+				{append(make([]byte, 128), append(hdr, obj...)...), 129, 128, nil},
+
+				{append(make([]byte, 512), append(hdr, obj...)...), 511, -1, errNoExtension},
+				{append(make([]byte, 512), append(hdr, obj...)...), 512, 512, nil},
+				{append(make([]byte, 512), append(hdr, obj...)...), 513, -1, errNoExtension},
+			} {
+				exts, l, err := parseExtensions(typ, wire.data, wire.inlattr)
+				if err != wire.err {
+					return fmt.Errorf("#%d: got %v; want %v", i, err, wire.err)
+				}
+				if wire.err != nil {
+					continue
+				}
+				if l != wire.outlattr {
+					return fmt.Errorf("#%d: got %d; want %d", i, l, wire.outlattr)
+				}
+				if !reflect.DeepEqual(exts, []Extension{te}) {
+					return fmt.Errorf("#%d: got %#v; want %#v", i, exts[0], te)
+				}
+			}
+		}
+		return nil
+	}
+
+	t.Run("MPLSLabelStack", func(t *testing.T) {
+		for _, et := range []struct {
+			proto int
+			typ   Type
+			hdr   []byte
+			obj   []byte
+			ext   Extension
+		}{
+			// MPLS label stack with no label
+			{
+				proto: iana.ProtocolICMP,
+				typ:   ipv4.ICMPTypeDestinationUnreachable,
+				hdr: []byte{
+					0x20, 0x00, 0x00, 0x00,
+				},
+				obj: []byte{
+					0x00, 0x04, 0x01, 0x01,
+				},
+				ext: &MPLSLabelStack{
+					Class: classMPLSLabelStack,
+					Type:  typeIncomingMPLSLabelStack,
+				},
 			},
 			},
-		},
-	},
-	// MPLS label stack with a single label
-	{
-		proto: iana.ProtocolIPv6ICMP,
-		hdr: []byte{
-			0x20, 0x00, 0x00, 0x00,
-		},
-		obj: []byte{
-			0x00, 0x08, 0x01, 0x01,
-			0x03, 0xe8, 0xe9, 0xff,
-		},
-		exts: []Extension{
-			&MPLSLabelStack{
-				Class: classMPLSLabelStack,
-				Type:  typeIncomingMPLSLabelStack,
-				Labels: []MPLSLabel{
-					{
-						Label: 16014,
-						TC:    0x4,
-						S:     true,
-						TTL:   255,
+			// MPLS label stack with a single label
+			{
+				proto: iana.ProtocolIPv6ICMP,
+				typ:   ipv6.ICMPTypeDestinationUnreachable,
+				hdr: []byte{
+					0x20, 0x00, 0x00, 0x00,
+				},
+				obj: []byte{
+					0x00, 0x08, 0x01, 0x01,
+					0x03, 0xe8, 0xe9, 0xff,
+				},
+				ext: &MPLSLabelStack{
+					Class: classMPLSLabelStack,
+					Type:  typeIncomingMPLSLabelStack,
+					Labels: []MPLSLabel{
+						{
+							Label: 16014,
+							TC:    0x4,
+							S:     true,
+							TTL:   255,
+						},
 					},
 					},
 				},
 				},
 			},
 			},
-		},
-	},
-	// MPLS label stack with multiple labels
-	{
-		proto: iana.ProtocolICMP,
-		hdr: []byte{
-			0x20, 0x00, 0x00, 0x00,
-		},
-		obj: []byte{
-			0x00, 0x0c, 0x01, 0x01,
-			0x03, 0xe8, 0xde, 0xfe,
-			0x03, 0xe8, 0xe1, 0xff,
-		},
-		exts: []Extension{
-			&MPLSLabelStack{
-				Class: classMPLSLabelStack,
-				Type:  typeIncomingMPLSLabelStack,
-				Labels: []MPLSLabel{
-					{
-						Label: 16013,
-						TC:    0x7,
-						S:     false,
-						TTL:   254,
-					},
-					{
-						Label: 16014,
-						TC:    0,
-						S:     true,
-						TTL:   255,
+			// MPLS label stack with multiple labels
+			{
+				proto: iana.ProtocolICMP,
+				typ:   ipv4.ICMPTypeDestinationUnreachable,
+				hdr: []byte{
+					0x20, 0x00, 0x00, 0x00,
+				},
+				obj: []byte{
+					0x00, 0x0c, 0x01, 0x01,
+					0x03, 0xe8, 0xde, 0xfe,
+					0x03, 0xe8, 0xe1, 0xff,
+				},
+				ext: &MPLSLabelStack{
+					Class: classMPLSLabelStack,
+					Type:  typeIncomingMPLSLabelStack,
+					Labels: []MPLSLabel{
+						{
+							Label: 16013,
+							TC:    0x7,
+							S:     false,
+							TTL:   254,
+						},
+						{
+							Label: 16014,
+							TC:    0,
+							S:     true,
+							TTL:   255,
+						},
 					},
 					},
 				},
 				},
 			},
 			},
-		},
-	},
-	// Interface information with no attribute
-	{
-		proto: iana.ProtocolICMP,
-		hdr: []byte{
-			0x20, 0x00, 0x00, 0x00,
-		},
-		obj: []byte{
-			0x00, 0x04, 0x02, 0x00,
-		},
-		exts: []Extension{
-			&InterfaceInfo{
-				Class: classInterfaceInfo,
+		} {
+			if err := fn(t, et.proto, et.typ, et.hdr, et.obj, et.ext); err != nil {
+				t.Error(err)
+			}
+		}
+	})
+	t.Run("InterfaceInfo", func(t *testing.T) {
+		for _, et := range []struct {
+			proto int
+			typ   Type
+			hdr   []byte
+			obj   []byte
+			ext   Extension
+		}{
+			// Interface information with no attribute
+			{
+				proto: iana.ProtocolICMP,
+				typ:   ipv4.ICMPTypeDestinationUnreachable,
+				hdr: []byte{
+					0x20, 0x00, 0x00, 0x00,
+				},
+				obj: []byte{
+					0x00, 0x04, 0x02, 0x00,
+				},
+				ext: &InterfaceInfo{
+					Class: classInterfaceInfo,
+				},
 			},
 			},
-		},
-	},
-	// Interface information with ifIndex and name
-	{
-		proto: iana.ProtocolICMP,
-		hdr: []byte{
-			0x20, 0x00, 0x00, 0x00,
-		},
-		obj: []byte{
-			0x00, 0x10, 0x02, 0x0a,
-			0x00, 0x00, 0x00, 0x10,
-			0x08, byte('e'), byte('n'), byte('1'),
-			byte('0'), byte('1'), 0x00, 0x00,
-		},
-		exts: []Extension{
-			&InterfaceInfo{
-				Class: classInterfaceInfo,
-				Type:  0x0a,
-				Interface: &net.Interface{
-					Index: 16,
-					Name:  "en101",
+			// Interface information with ifIndex and name
+			{
+				proto: iana.ProtocolICMP,
+				typ:   ipv4.ICMPTypeDestinationUnreachable,
+				hdr: []byte{
+					0x20, 0x00, 0x00, 0x00,
+				},
+				obj: []byte{
+					0x00, 0x10, 0x02, 0x0a,
+					0x00, 0x00, 0x00, 0x10,
+					0x08, byte('e'), byte('n'), byte('1'),
+					byte('0'), byte('1'), 0x00, 0x00,
+				},
+				ext: &InterfaceInfo{
+					Class: classInterfaceInfo,
+					Type:  0x0a,
+					Interface: &net.Interface{
+						Index: 16,
+						Name:  "en101",
+					},
 				},
 				},
 			},
 			},
-		},
-	},
-	// Interface information with ifIndex, IPAddr, name and MTU
-	{
-		proto: iana.ProtocolIPv6ICMP,
-		hdr: []byte{
-			0x20, 0x00, 0x00, 0x00,
-		},
-		obj: []byte{
-			0x00, 0x28, 0x02, 0x0f,
-			0x00, 0x00, 0x00, 0x0f,
-			0x00, 0x02, 0x00, 0x00,
-			0xfe, 0x80, 0x00, 0x00,
-			0x00, 0x00, 0x00, 0x00,
-			0x00, 0x00, 0x00, 0x00,
-			0x00, 0x00, 0x00, 0x01,
-			0x08, byte('e'), byte('n'), byte('1'),
-			byte('0'), byte('1'), 0x00, 0x00,
-			0x00, 0x00, 0x20, 0x00,
-		},
-		exts: []Extension{
-			&InterfaceInfo{
-				Class: classInterfaceInfo,
-				Type:  0x0f,
-				Interface: &net.Interface{
-					Index: 15,
-					Name:  "en101",
-					MTU:   8192,
+			// Interface information with ifIndex, IPAddr, name and MTU
+			{
+				proto: iana.ProtocolIPv6ICMP,
+				typ:   ipv6.ICMPTypeDestinationUnreachable,
+				hdr: []byte{
+					0x20, 0x00, 0x00, 0x00,
 				},
 				},
-				Addr: &net.IPAddr{
-					IP:   net.ParseIP("fe80::1"),
-					Zone: "en101",
+				obj: []byte{
+					0x00, 0x28, 0x02, 0x0f,
+					0x00, 0x00, 0x00, 0x0f,
+					0x00, 0x02, 0x00, 0x00,
+					0xfe, 0x80, 0x00, 0x00,
+					0x00, 0x00, 0x00, 0x00,
+					0x00, 0x00, 0x00, 0x00,
+					0x00, 0x00, 0x00, 0x01,
+					0x08, byte('e'), byte('n'), byte('1'),
+					byte('0'), byte('1'), 0x00, 0x00,
+					0x00, 0x00, 0x20, 0x00,
+				},
+				ext: &InterfaceInfo{
+					Class: classInterfaceInfo,
+					Type:  0x0f,
+					Interface: &net.Interface{
+						Index: 15,
+						Name:  "en101",
+						MTU:   8192,
+					},
+					Addr: &net.IPAddr{
+						IP:   net.ParseIP("fe80::1"),
+						Zone: "en101",
+					},
 				},
 				},
 			},
 			},
-		},
-	},
-}
-
-func TestMarshalAndParseExtension(t *testing.T) {
-	for i, tt := range marshalAndParseExtensionTests {
-		for j, ext := range tt.exts {
-			var err error
-			var b []byte
-			switch ext := ext.(type) {
-			case *MPLSLabelStack:
-				b, err = ext.Marshal(tt.proto)
-				if err != nil {
-					t.Errorf("#%v/%v: %v", i, j, err)
-					continue
-				}
-			case *InterfaceInfo:
-				b, err = ext.Marshal(tt.proto)
-				if err != nil {
-					t.Errorf("#%v/%v: %v", i, j, err)
-					continue
-				}
-			}
-			if !reflect.DeepEqual(b, tt.obj) {
-				t.Errorf("#%v/%v: got %#v; want %#v", i, j, b, tt.obj)
-				continue
+		} {
+			if err := fn(t, et.proto, et.typ, et.hdr, et.obj, et.ext); err != nil {
+				t.Error(err)
 			}
 			}
 		}
 		}
-
-		for j, wire := range []struct {
-			data     []byte // original datagram
-			inlattr  int    // length of padded original datagram, a hint
-			outlattr int    // length of padded original datagram, a want
-			err      error
+	})
+	t.Run("InterfaceIdent", func(t *testing.T) {
+		for _, et := range []struct {
+			proto int
+			typ   Type
+			hdr   []byte
+			obj   []byte
+			ext   Extension
 		}{
 		}{
-			{nil, 0, -1, errNoExtension},
-			{make([]byte, 127), 128, -1, errNoExtension},
-
-			{make([]byte, 128), 127, -1, errNoExtension},
-			{make([]byte, 128), 128, -1, errNoExtension},
-			{make([]byte, 128), 129, -1, errNoExtension},
-
-			{append(make([]byte, 128), append(tt.hdr, tt.obj...)...), 127, 128, nil},
-			{append(make([]byte, 128), append(tt.hdr, tt.obj...)...), 128, 128, nil},
-			{append(make([]byte, 128), append(tt.hdr, tt.obj...)...), 129, 128, nil},
-
-			{append(make([]byte, 512), append(tt.hdr, tt.obj...)...), 511, -1, errNoExtension},
-			{append(make([]byte, 512), append(tt.hdr, tt.obj...)...), 512, 512, nil},
-			{append(make([]byte, 512), append(tt.hdr, tt.obj...)...), 513, -1, errNoExtension},
+			// Interface identification by name
+			{
+				proto: iana.ProtocolICMP,
+				typ:   ipv4.ICMPTypeExtendedEchoRequest,
+				hdr: []byte{
+					0x20, 0x00, 0x00, 0x00,
+				},
+				obj: []byte{
+					0x00, 0x0c, 0x03, 0x01,
+					byte('e'), byte('n'), byte('1'), byte('0'),
+					byte('1'), 0x00, 0x00, 0x00,
+				},
+				ext: &InterfaceIdent{
+					Class: classInterfaceIdent,
+					Type:  typeInterfaceByName,
+					Name:  "en101",
+				},
+			},
+			// Interface identification by index
+			{
+				proto: iana.ProtocolIPv6ICMP,
+				typ:   ipv6.ICMPTypeExtendedEchoRequest,
+				hdr: []byte{
+					0x20, 0x00, 0x00, 0x00,
+				},
+				obj: []byte{
+					0x00, 0x0c, 0x03, 0x02,
+					0x00, 0x00, 0x00, 0x00,
+					0x00, 0x00, 0x03, 0x8f,
+				},
+				ext: &InterfaceIdent{
+					Class: classInterfaceIdent,
+					Type:  typeInterfaceByIndex,
+					Index: 911,
+				},
+			},
+			// Interface identification by address
+			{
+				proto: iana.ProtocolICMP,
+				typ:   ipv4.ICMPTypeExtendedEchoRequest,
+				hdr: []byte{
+					0x20, 0x00, 0x00, 0x00,
+				},
+				obj: []byte{
+					0x00, 0x10, 0x03, 0x03,
+					byte(iana.AddrFamily48bitMAC >> 8), byte(iana.AddrFamily48bitMAC & 0x0f), 0x06, 0x00,
+					0x01, 0x23, 0x45, 0x67,
+					0x89, 0xab, 0x00, 0x00,
+				},
+				ext: &InterfaceIdent{
+					Class: classInterfaceIdent,
+					Type:  typeInterfaceByAddress,
+					AFI:   iana.AddrFamily48bitMAC,
+					Addr:  []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab},
+				},
+			},
 		} {
 		} {
-			exts, l, err := parseExtensions(wire.data, wire.inlattr)
-			if err != wire.err {
-				t.Errorf("#%v/%v: got %v; want %v", i, j, err, wire.err)
-				continue
-			}
-			if wire.err != nil {
-				continue
-			}
-			if l != wire.outlattr {
-				t.Errorf("#%v/%v: got %v; want %v", i, j, l, wire.outlattr)
-			}
-			if !reflect.DeepEqual(exts, tt.exts) {
-				for j, ext := range exts {
-					switch ext := ext.(type) {
-					case *MPLSLabelStack:
-						want := tt.exts[j].(*MPLSLabelStack)
-						t.Errorf("#%v/%v: got %#v; want %#v", i, j, ext, want)
-					case *InterfaceInfo:
-						want := tt.exts[j].(*InterfaceInfo)
-						t.Errorf("#%v/%v: got %#v; want %#v", i, j, ext, want)
-					}
-				}
-				continue
+			if err := fn(t, et.proto, et.typ, et.hdr, et.obj, et.ext); err != nil {
+				t.Error(err)
 			}
 			}
 		}
 		}
-	}
-}
-
-var parseInterfaceNameTests = []struct {
-	b []byte
-	error
-}{
-	{[]byte{0, 'e', 'n', '0'}, errInvalidExtension},
-	{[]byte{4, 'e', 'n', '0'}, nil},
-	{[]byte{7, 'e', 'n', '0', 0xff, 0xff, 0xff, 0xff}, errInvalidExtension},
-	{[]byte{8, 'e', 'n', '0', 0xff, 0xff, 0xff}, errMessageTooShort},
+	})
 }
 }
 
 
 func TestParseInterfaceName(t *testing.T) {
 func TestParseInterfaceName(t *testing.T) {
 	ifi := InterfaceInfo{Interface: &net.Interface{}}
 	ifi := InterfaceInfo{Interface: &net.Interface{}}
-	for i, tt := range parseInterfaceNameTests {
+	for i, tt := range []struct {
+		b []byte
+		error
+	}{
+		{[]byte{0, 'e', 'n', '0'}, errInvalidExtension},
+		{[]byte{4, 'e', 'n', '0'}, nil},
+		{[]byte{7, 'e', 'n', '0', 0xff, 0xff, 0xff, 0xff}, errInvalidExtension},
+		{[]byte{8, 'e', 'n', '0', 0xff, 0xff, 0xff}, errMessageTooShort},
+	} {
 		if _, err := ifi.parseName(tt.b); err != tt.error {
 		if _, err := ifi.parseName(tt.b); err != tt.error {
 			t.Errorf("#%d: got %v; want %v", i, err, tt.error)
 			t.Errorf("#%d: got %v; want %v", i, err, tt.error)
 		}
 		}

+ 0 - 27
vendor/golang.org/x/net/icmp/helper.go

@@ -1,27 +0,0 @@
-// Copyright 2016 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package icmp
-
-import (
-	"encoding/binary"
-	"unsafe"
-)
-
-var (
-	// See http://www.freebsd.org/doc/en/books/porters-handbook/freebsd-versions.html.
-	freebsdVersion uint32
-
-	nativeEndian binary.ByteOrder
-)
-
-func init() {
-	i := uint32(1)
-	b := (*[4]byte)(unsafe.Pointer(&i))
-	if b[0] == 1 {
-		nativeEndian = binary.LittleEndian
-	} else {
-		nativeEndian = binary.BigEndian
-	}
-}

+ 93 - 7
vendor/golang.org/x/net/icmp/interface.go

@@ -14,9 +14,6 @@ import (
 
 
 const (
 const (
 	classInterfaceInfo = 2
 	classInterfaceInfo = 2
-
-	afiIPv4 = 1
-	afiIPv6 = 2
 )
 )
 
 
 const (
 const (
@@ -127,11 +124,11 @@ func (ifi *InterfaceInfo) parseIfIndex(b []byte) ([]byte, error) {
 func (ifi *InterfaceInfo) marshalIPAddr(proto int, b []byte) []byte {
 func (ifi *InterfaceInfo) marshalIPAddr(proto int, b []byte) []byte {
 	switch proto {
 	switch proto {
 	case iana.ProtocolICMP:
 	case iana.ProtocolICMP:
-		binary.BigEndian.PutUint16(b[:2], uint16(afiIPv4))
+		binary.BigEndian.PutUint16(b[:2], uint16(iana.AddrFamilyIPv4))
 		copy(b[4:4+net.IPv4len], ifi.Addr.IP.To4())
 		copy(b[4:4+net.IPv4len], ifi.Addr.IP.To4())
 		b = b[4+net.IPv4len:]
 		b = b[4+net.IPv4len:]
 	case iana.ProtocolIPv6ICMP:
 	case iana.ProtocolIPv6ICMP:
-		binary.BigEndian.PutUint16(b[:2], uint16(afiIPv6))
+		binary.BigEndian.PutUint16(b[:2], uint16(iana.AddrFamilyIPv6))
 		copy(b[4:4+net.IPv6len], ifi.Addr.IP.To16())
 		copy(b[4:4+net.IPv6len], ifi.Addr.IP.To16())
 		b = b[4+net.IPv6len:]
 		b = b[4+net.IPv6len:]
 	}
 	}
@@ -145,14 +142,14 @@ func (ifi *InterfaceInfo) parseIPAddr(b []byte) ([]byte, error) {
 	afi := int(binary.BigEndian.Uint16(b[:2]))
 	afi := int(binary.BigEndian.Uint16(b[:2]))
 	b = b[4:]
 	b = b[4:]
 	switch afi {
 	switch afi {
-	case afiIPv4:
+	case iana.AddrFamilyIPv4:
 		if len(b) < net.IPv4len {
 		if len(b) < net.IPv4len {
 			return nil, errMessageTooShort
 			return nil, errMessageTooShort
 		}
 		}
 		ifi.Addr.IP = make(net.IP, net.IPv4len)
 		ifi.Addr.IP = make(net.IP, net.IPv4len)
 		copy(ifi.Addr.IP, b[:net.IPv4len])
 		copy(ifi.Addr.IP, b[:net.IPv4len])
 		b = b[net.IPv4len:]
 		b = b[net.IPv4len:]
-	case afiIPv6:
+	case iana.AddrFamilyIPv6:
 		if len(b) < net.IPv6len {
 		if len(b) < net.IPv6len {
 			return nil, errMessageTooShort
 			return nil, errMessageTooShort
 		}
 		}
@@ -234,3 +231,92 @@ func parseInterfaceInfo(b []byte) (Extension, error) {
 	}
 	}
 	return ifi, nil
 	return ifi, nil
 }
 }
+
+const (
+	classInterfaceIdent    = 3
+	typeInterfaceByName    = 1
+	typeInterfaceByIndex   = 2
+	typeInterfaceByAddress = 3
+)
+
+// An InterfaceIdent represents interface identification.
+type InterfaceIdent struct {
+	Class int    // extension object class number
+	Type  int    // extension object sub-type
+	Name  string // interface name
+	Index int    // interface index
+	AFI   int    // address family identifier; see address family numbers in IANA registry
+	Addr  []byte // address
+}
+
+// Len implements the Len method of Extension interface.
+func (ifi *InterfaceIdent) Len(_ int) int {
+	switch ifi.Type {
+	case typeInterfaceByName:
+		l := len(ifi.Name)
+		if l > 255 {
+			l = 255
+		}
+		return 4 + (l+3)&^3
+	case typeInterfaceByIndex:
+		return 4 + 8
+	case typeInterfaceByAddress:
+		return 4 + 4 + (len(ifi.Addr)+3)&^3
+	default:
+		return 4
+	}
+}
+
+// Marshal implements the Marshal method of Extension interface.
+func (ifi *InterfaceIdent) Marshal(proto int) ([]byte, error) {
+	b := make([]byte, ifi.Len(proto))
+	if err := ifi.marshal(proto, b); err != nil {
+		return nil, err
+	}
+	return b, nil
+}
+
+func (ifi *InterfaceIdent) marshal(proto int, b []byte) error {
+	l := ifi.Len(proto)
+	binary.BigEndian.PutUint16(b[:2], uint16(l))
+	b[2], b[3] = classInterfaceIdent, byte(ifi.Type)
+	switch ifi.Type {
+	case typeInterfaceByName:
+		copy(b[4:], ifi.Name)
+	case typeInterfaceByIndex:
+		binary.BigEndian.PutUint64(b[4:4+8], uint64(ifi.Index))
+	case typeInterfaceByAddress:
+		binary.BigEndian.PutUint16(b[4:4+2], uint16(ifi.AFI))
+		b[4+2] = byte(len(ifi.Addr))
+		copy(b[4+4:], ifi.Addr)
+	}
+	return nil
+}
+
+func parseInterfaceIdent(b []byte) (Extension, error) {
+	ifi := &InterfaceIdent{
+		Class: int(b[2]),
+		Type:  int(b[3]),
+	}
+	switch ifi.Type {
+	case typeInterfaceByName:
+		ifi.Name = strings.Trim(string(b[4:]), string(0))
+	case typeInterfaceByIndex:
+		if len(b[4:]) < 8 {
+			return nil, errInvalidExtension
+		}
+		ifi.Index = int(binary.BigEndian.Uint64(b[4 : 4+8]))
+	case typeInterfaceByAddress:
+		if len(b[4:]) < 4 {
+			return nil, errInvalidExtension
+		}
+		ifi.AFI = int(binary.BigEndian.Uint16(b[4 : 4+2]))
+		l := int(b[4+2])
+		if len(b[4+4:]) < l {
+			return nil, errInvalidExtension
+		}
+		ifi.Addr = make([]byte, l)
+		copy(ifi.Addr, b[4+4:])
+	}
+	return ifi, nil
+}

+ 7 - 2
vendor/golang.org/x/net/icmp/ipv4.go

@@ -9,9 +9,14 @@ import (
 	"net"
 	"net"
 	"runtime"
 	"runtime"
 
 
+	"golang.org/x/net/internal/socket"
 	"golang.org/x/net/ipv4"
 	"golang.org/x/net/ipv4"
 )
 )
 
 
+// freebsdVersion is set in sys_freebsd.go.
+// See http://www.freebsd.org/doc/en/books/porters-handbook/freebsd-versions.html.
+var freebsdVersion uint32
+
 // ParseIPv4Header parses b as an IPv4 header of ICMP error message
 // ParseIPv4Header parses b as an IPv4 header of ICMP error message
 // invoking packet, which is contained in ICMP error message.
 // invoking packet, which is contained in ICMP error message.
 func ParseIPv4Header(b []byte) (*ipv4.Header, error) {
 func ParseIPv4Header(b []byte) (*ipv4.Header, error) {
@@ -36,12 +41,12 @@ func ParseIPv4Header(b []byte) (*ipv4.Header, error) {
 	}
 	}
 	switch runtime.GOOS {
 	switch runtime.GOOS {
 	case "darwin":
 	case "darwin":
-		h.TotalLen = int(nativeEndian.Uint16(b[2:4]))
+		h.TotalLen = int(socket.NativeEndian.Uint16(b[2:4]))
 	case "freebsd":
 	case "freebsd":
 		if freebsdVersion >= 1000000 {
 		if freebsdVersion >= 1000000 {
 			h.TotalLen = int(binary.BigEndian.Uint16(b[2:4]))
 			h.TotalLen = int(binary.BigEndian.Uint16(b[2:4]))
 		} else {
 		} else {
-			h.TotalLen = int(nativeEndian.Uint16(b[2:4]))
+			h.TotalLen = int(socket.NativeEndian.Uint16(b[2:4]))
 		}
 		}
 	default:
 	default:
 		h.TotalLen = int(binary.BigEndian.Uint16(b[2:4]))
 		h.TotalLen = int(binary.BigEndian.Uint16(b[2:4]))

+ 56 - 63
vendor/golang.org/x/net/icmp/ipv4_test.go

@@ -11,72 +11,65 @@ import (
 	"runtime"
 	"runtime"
 	"testing"
 	"testing"
 
 
+	"golang.org/x/net/internal/socket"
 	"golang.org/x/net/ipv4"
 	"golang.org/x/net/ipv4"
 )
 )
 
 
-type ipv4HeaderTest struct {
-	wireHeaderFromKernel        [ipv4.HeaderLen]byte
-	wireHeaderFromTradBSDKernel [ipv4.HeaderLen]byte
-	Header                      *ipv4.Header
-}
-
-var ipv4HeaderLittleEndianTest = ipv4HeaderTest{
-	// TODO(mikio): Add platform dependent wire header formats when
-	// we support new platforms.
-	wireHeaderFromKernel: [ipv4.HeaderLen]byte{
-		0x45, 0x01, 0xbe, 0xef,
-		0xca, 0xfe, 0x45, 0xdc,
-		0xff, 0x01, 0xde, 0xad,
-		172, 16, 254, 254,
-		192, 168, 0, 1,
-	},
-	wireHeaderFromTradBSDKernel: [ipv4.HeaderLen]byte{
-		0x45, 0x01, 0xef, 0xbe,
-		0xca, 0xfe, 0x45, 0xdc,
-		0xff, 0x01, 0xde, 0xad,
-		172, 16, 254, 254,
-		192, 168, 0, 1,
-	},
-	Header: &ipv4.Header{
-		Version:  ipv4.Version,
-		Len:      ipv4.HeaderLen,
-		TOS:      1,
-		TotalLen: 0xbeef,
-		ID:       0xcafe,
-		Flags:    ipv4.DontFragment,
-		FragOff:  1500,
-		TTL:      255,
-		Protocol: 1,
-		Checksum: 0xdead,
-		Src:      net.IPv4(172, 16, 254, 254),
-		Dst:      net.IPv4(192, 168, 0, 1),
-	},
-}
-
 func TestParseIPv4Header(t *testing.T) {
 func TestParseIPv4Header(t *testing.T) {
-	tt := &ipv4HeaderLittleEndianTest
-	if nativeEndian != binary.LittleEndian {
-		t.Skip("no test for non-little endian machine yet")
-	}
-
-	var wh []byte
-	switch runtime.GOOS {
-	case "darwin":
-		wh = tt.wireHeaderFromTradBSDKernel[:]
-	case "freebsd":
-		if freebsdVersion >= 1000000 {
-			wh = tt.wireHeaderFromKernel[:]
-		} else {
-			wh = tt.wireHeaderFromTradBSDKernel[:]
-		}
-	default:
-		wh = tt.wireHeaderFromKernel[:]
-	}
-	h, err := ParseIPv4Header(wh)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if !reflect.DeepEqual(h, tt.Header) {
-		t.Fatalf("got %#v; want %#v", h, tt.Header)
+	switch socket.NativeEndian {
+	case binary.LittleEndian:
+		t.Run("LittleEndian", func(t *testing.T) {
+			// TODO(mikio): Add platform dependent wire
+			// header formats when we support new
+			// platforms.
+			wireHeaderFromKernel := [ipv4.HeaderLen]byte{
+				0x45, 0x01, 0xbe, 0xef,
+				0xca, 0xfe, 0x45, 0xdc,
+				0xff, 0x01, 0xde, 0xad,
+				172, 16, 254, 254,
+				192, 168, 0, 1,
+			}
+			wireHeaderFromTradBSDKernel := [ipv4.HeaderLen]byte{
+				0x45, 0x01, 0xef, 0xbe,
+				0xca, 0xfe, 0x45, 0xdc,
+				0xff, 0x01, 0xde, 0xad,
+				172, 16, 254, 254,
+				192, 168, 0, 1,
+			}
+			th := &ipv4.Header{
+				Version:  ipv4.Version,
+				Len:      ipv4.HeaderLen,
+				TOS:      1,
+				TotalLen: 0xbeef,
+				ID:       0xcafe,
+				Flags:    ipv4.DontFragment,
+				FragOff:  1500,
+				TTL:      255,
+				Protocol: 1,
+				Checksum: 0xdead,
+				Src:      net.IPv4(172, 16, 254, 254),
+				Dst:      net.IPv4(192, 168, 0, 1),
+			}
+			var wh []byte
+			switch runtime.GOOS {
+			case "darwin":
+				wh = wireHeaderFromTradBSDKernel[:]
+			case "freebsd":
+				if freebsdVersion >= 1000000 {
+					wh = wireHeaderFromKernel[:]
+				} else {
+					wh = wireHeaderFromTradBSDKernel[:]
+				}
+			default:
+				wh = wireHeaderFromKernel[:]
+			}
+			h, err := ParseIPv4Header(wh)
+			if err != nil {
+				t.Fatal(err)
+			}
+			if !reflect.DeepEqual(h, th) {
+				t.Fatalf("got %#v; want %#v", h, th)
+			}
+		})
 	}
 	}
 }
 }

+ 11 - 6
vendor/golang.org/x/net/icmp/message.go

@@ -11,6 +11,7 @@
 // ICMP extensions for MPLS are defined in RFC 4950.
 // ICMP extensions for MPLS are defined in RFC 4950.
 // ICMP extensions for interface and next-hop identification are
 // ICMP extensions for interface and next-hop identification are
 // defined in RFC 5837.
 // defined in RFC 5837.
+// PROBE: A utility for probing interfaces is defined in RFC 8335.
 package icmp // import "golang.org/x/net/icmp"
 package icmp // import "golang.org/x/net/icmp"
 
 
 import (
 import (
@@ -107,21 +108,25 @@ func (m *Message) Marshal(psh []byte) ([]byte, error) {
 	return b[len(psh):], nil
 	return b[len(psh):], nil
 }
 }
 
 
-var parseFns = map[Type]func(int, []byte) (MessageBody, error){
+var parseFns = map[Type]func(int, Type, []byte) (MessageBody, error){
 	ipv4.ICMPTypeDestinationUnreachable: parseDstUnreach,
 	ipv4.ICMPTypeDestinationUnreachable: parseDstUnreach,
 	ipv4.ICMPTypeTimeExceeded:           parseTimeExceeded,
 	ipv4.ICMPTypeTimeExceeded:           parseTimeExceeded,
 	ipv4.ICMPTypeParameterProblem:       parseParamProb,
 	ipv4.ICMPTypeParameterProblem:       parseParamProb,
 
 
-	ipv4.ICMPTypeEcho:      parseEcho,
-	ipv4.ICMPTypeEchoReply: parseEcho,
+	ipv4.ICMPTypeEcho:                parseEcho,
+	ipv4.ICMPTypeEchoReply:           parseEcho,
+	ipv4.ICMPTypeExtendedEchoRequest: parseExtendedEchoRequest,
+	ipv4.ICMPTypeExtendedEchoReply:   parseExtendedEchoReply,
 
 
 	ipv6.ICMPTypeDestinationUnreachable: parseDstUnreach,
 	ipv6.ICMPTypeDestinationUnreachable: parseDstUnreach,
 	ipv6.ICMPTypePacketTooBig:           parsePacketTooBig,
 	ipv6.ICMPTypePacketTooBig:           parsePacketTooBig,
 	ipv6.ICMPTypeTimeExceeded:           parseTimeExceeded,
 	ipv6.ICMPTypeTimeExceeded:           parseTimeExceeded,
 	ipv6.ICMPTypeParameterProblem:       parseParamProb,
 	ipv6.ICMPTypeParameterProblem:       parseParamProb,
 
 
-	ipv6.ICMPTypeEchoRequest: parseEcho,
-	ipv6.ICMPTypeEchoReply:   parseEcho,
+	ipv6.ICMPTypeEchoRequest:         parseEcho,
+	ipv6.ICMPTypeEchoReply:           parseEcho,
+	ipv6.ICMPTypeExtendedEchoRequest: parseExtendedEchoRequest,
+	ipv6.ICMPTypeExtendedEchoReply:   parseExtendedEchoReply,
 }
 }
 
 
 // ParseMessage parses b as an ICMP message.
 // ParseMessage parses b as an ICMP message.
@@ -143,7 +148,7 @@ func ParseMessage(proto int, b []byte) (*Message, error) {
 	if fn, ok := parseFns[m.Type]; !ok {
 	if fn, ok := parseFns[m.Type]; !ok {
 		m.Body, err = parseDefaultMessageBody(proto, b[4:])
 		m.Body, err = parseDefaultMessageBody(proto, b[4:])
 	} else {
 	} else {
-		m.Body, err = fn(proto, b[4:])
+		m.Body, err = fn(proto, m.Type, b[4:])
 	}
 	}
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err

+ 133 - 112
vendor/golang.org/x/net/icmp/message_test.go

@@ -15,120 +15,141 @@ import (
 	"golang.org/x/net/ipv6"
 	"golang.org/x/net/ipv6"
 )
 )
 
 
-var marshalAndParseMessageForIPv4Tests = []icmp.Message{
-	{
-		Type: ipv4.ICMPTypeDestinationUnreachable, Code: 15,
-		Body: &icmp.DstUnreach{
-			Data: []byte("ERROR-INVOKING-PACKET"),
-		},
-	},
-	{
-		Type: ipv4.ICMPTypeTimeExceeded, Code: 1,
-		Body: &icmp.TimeExceeded{
-			Data: []byte("ERROR-INVOKING-PACKET"),
-		},
-	},
-	{
-		Type: ipv4.ICMPTypeParameterProblem, Code: 2,
-		Body: &icmp.ParamProb{
-			Pointer: 8,
-			Data:    []byte("ERROR-INVOKING-PACKET"),
-		},
-	},
-	{
-		Type: ipv4.ICMPTypeEcho, Code: 0,
-		Body: &icmp.Echo{
-			ID: 1, Seq: 2,
-			Data: []byte("HELLO-R-U-THERE"),
-		},
-	},
-	{
-		Type: ipv4.ICMPTypePhoturis,
-		Body: &icmp.DefaultMessageBody{
-			Data: []byte{0x80, 0x40, 0x20, 0x10},
-		},
-	},
-}
-
-func TestMarshalAndParseMessageForIPv4(t *testing.T) {
-	for i, tt := range marshalAndParseMessageForIPv4Tests {
-		b, err := tt.Marshal(nil)
-		if err != nil {
-			t.Fatal(err)
-		}
-		m, err := icmp.ParseMessage(iana.ProtocolICMP, b)
-		if err != nil {
-			t.Fatal(err)
-		}
-		if m.Type != tt.Type || m.Code != tt.Code {
-			t.Errorf("#%v: got %v; want %v", i, m, &tt)
-		}
-		if !reflect.DeepEqual(m.Body, tt.Body) {
-			t.Errorf("#%v: got %v; want %v", i, m.Body, tt.Body)
-		}
-	}
-}
-
-var marshalAndParseMessageForIPv6Tests = []icmp.Message{
-	{
-		Type: ipv6.ICMPTypeDestinationUnreachable, Code: 6,
-		Body: &icmp.DstUnreach{
-			Data: []byte("ERROR-INVOKING-PACKET"),
-		},
-	},
-	{
-		Type: ipv6.ICMPTypePacketTooBig, Code: 0,
-		Body: &icmp.PacketTooBig{
-			MTU:  1<<16 - 1,
-			Data: []byte("ERROR-INVOKING-PACKET"),
-		},
-	},
-	{
-		Type: ipv6.ICMPTypeTimeExceeded, Code: 1,
-		Body: &icmp.TimeExceeded{
-			Data: []byte("ERROR-INVOKING-PACKET"),
-		},
-	},
-	{
-		Type: ipv6.ICMPTypeParameterProblem, Code: 2,
-		Body: &icmp.ParamProb{
-			Pointer: 8,
-			Data:    []byte("ERROR-INVOKING-PACKET"),
-		},
-	},
-	{
-		Type: ipv6.ICMPTypeEchoRequest, Code: 0,
-		Body: &icmp.Echo{
-			ID: 1, Seq: 2,
-			Data: []byte("HELLO-R-U-THERE"),
-		},
-	},
-	{
-		Type: ipv6.ICMPTypeDuplicateAddressConfirmation,
-		Body: &icmp.DefaultMessageBody{
-			Data: []byte{0x80, 0x40, 0x20, 0x10},
-		},
-	},
-}
-
-func TestMarshalAndParseMessageForIPv6(t *testing.T) {
-	pshicmp := icmp.IPv6PseudoHeader(net.ParseIP("fe80::1"), net.ParseIP("ff02::1"))
-	for i, tt := range marshalAndParseMessageForIPv6Tests {
-		for _, psh := range [][]byte{pshicmp, nil} {
-			b, err := tt.Marshal(psh)
-			if err != nil {
-				t.Fatal(err)
-			}
-			m, err := icmp.ParseMessage(iana.ProtocolIPv6ICMP, b)
-			if err != nil {
-				t.Fatal(err)
+func TestMarshalAndParseMessage(t *testing.T) {
+	fn := func(t *testing.T, proto int, tms []icmp.Message) {
+		var pshs [][]byte
+		switch proto {
+		case iana.ProtocolICMP:
+			pshs = [][]byte{nil}
+		case iana.ProtocolIPv6ICMP:
+			pshs = [][]byte{
+				icmp.IPv6PseudoHeader(net.ParseIP("fe80::1"), net.ParseIP("ff02::1")),
+				nil,
 			}
 			}
-			if m.Type != tt.Type || m.Code != tt.Code {
-				t.Errorf("#%v: got %v; want %v", i, m, &tt)
-			}
-			if !reflect.DeepEqual(m.Body, tt.Body) {
-				t.Errorf("#%v: got %v; want %v", i, m.Body, tt.Body)
+		}
+		for i, tm := range tms {
+			for _, psh := range pshs {
+				b, err := tm.Marshal(psh)
+				if err != nil {
+					t.Fatal(err)
+				}
+				m, err := icmp.ParseMessage(proto, b)
+				if err != nil {
+					t.Fatal(err)
+				}
+				if m.Type != tm.Type || m.Code != tm.Code {
+					t.Errorf("#%d: got %#v; want %#v", i, m, &tm)
+				}
+				if !reflect.DeepEqual(m.Body, tm.Body) {
+					t.Errorf("#%d: got %#v; want %#v", i, m.Body, tm.Body)
+				}
 			}
 			}
 		}
 		}
 	}
 	}
+
+	t.Run("IPv4", func(t *testing.T) {
+		fn(t, iana.ProtocolICMP,
+			[]icmp.Message{
+				{
+					Type: ipv4.ICMPTypeDestinationUnreachable, Code: 15,
+					Body: &icmp.DstUnreach{
+						Data: []byte("ERROR-INVOKING-PACKET"),
+					},
+				},
+				{
+					Type: ipv4.ICMPTypeTimeExceeded, Code: 1,
+					Body: &icmp.TimeExceeded{
+						Data: []byte("ERROR-INVOKING-PACKET"),
+					},
+				},
+				{
+					Type: ipv4.ICMPTypeParameterProblem, Code: 2,
+					Body: &icmp.ParamProb{
+						Pointer: 8,
+						Data:    []byte("ERROR-INVOKING-PACKET"),
+					},
+				},
+				{
+					Type: ipv4.ICMPTypeEcho, Code: 0,
+					Body: &icmp.Echo{
+						ID: 1, Seq: 2,
+						Data: []byte("HELLO-R-U-THERE"),
+					},
+				},
+				{
+					Type: ipv4.ICMPTypeExtendedEchoRequest, Code: 0,
+					Body: &icmp.ExtendedEchoRequest{
+						ID: 1, Seq: 2,
+					},
+				},
+				{
+					Type: ipv4.ICMPTypeExtendedEchoReply, Code: 0,
+					Body: &icmp.ExtendedEchoReply{
+						State: 4 /* Delay */, Active: true, IPv4: true,
+					},
+				},
+				{
+					Type: ipv4.ICMPTypePhoturis,
+					Body: &icmp.DefaultMessageBody{
+						Data: []byte{0x80, 0x40, 0x20, 0x10},
+					},
+				},
+			})
+	})
+	t.Run("IPv6", func(t *testing.T) {
+		fn(t, iana.ProtocolIPv6ICMP,
+			[]icmp.Message{
+				{
+					Type: ipv6.ICMPTypeDestinationUnreachable, Code: 6,
+					Body: &icmp.DstUnreach{
+						Data: []byte("ERROR-INVOKING-PACKET"),
+					},
+				},
+				{
+					Type: ipv6.ICMPTypePacketTooBig, Code: 0,
+					Body: &icmp.PacketTooBig{
+						MTU:  1<<16 - 1,
+						Data: []byte("ERROR-INVOKING-PACKET"),
+					},
+				},
+				{
+					Type: ipv6.ICMPTypeTimeExceeded, Code: 1,
+					Body: &icmp.TimeExceeded{
+						Data: []byte("ERROR-INVOKING-PACKET"),
+					},
+				},
+				{
+					Type: ipv6.ICMPTypeParameterProblem, Code: 2,
+					Body: &icmp.ParamProb{
+						Pointer: 8,
+						Data:    []byte("ERROR-INVOKING-PACKET"),
+					},
+				},
+				{
+					Type: ipv6.ICMPTypeEchoRequest, Code: 0,
+					Body: &icmp.Echo{
+						ID: 1, Seq: 2,
+						Data: []byte("HELLO-R-U-THERE"),
+					},
+				},
+				{
+					Type: ipv6.ICMPTypeExtendedEchoRequest, Code: 0,
+					Body: &icmp.ExtendedEchoRequest{
+						ID: 1, Seq: 2,
+					},
+				},
+				{
+					Type: ipv6.ICMPTypeExtendedEchoReply, Code: 0,
+					Body: &icmp.ExtendedEchoReply{
+						State: 5 /* Probe */, Active: true, IPv6: true,
+					},
+				},
+				{
+					Type: ipv6.ICMPTypeDuplicateAddressConfirmation,
+					Body: &icmp.DefaultMessageBody{
+						Data: []byte{0x80, 0x40, 0x20, 0x10},
+					},
+				},
+			})
+	})
 }
 }

+ 25 - 13
vendor/golang.org/x/net/icmp/multipart.go

@@ -10,12 +10,14 @@ import "golang.org/x/net/internal/iana"
 // exts as extensions, and returns a required length for message body
 // exts as extensions, and returns a required length for message body
 // and a required length for a padded original datagram in wire
 // and a required length for a padded original datagram in wire
 // format.
 // format.
-func multipartMessageBodyDataLen(proto int, b []byte, exts []Extension) (bodyLen, dataLen int) {
+func multipartMessageBodyDataLen(proto int, withOrigDgram bool, b []byte, exts []Extension) (bodyLen, dataLen int) {
 	for _, ext := range exts {
 	for _, ext := range exts {
 		bodyLen += ext.Len(proto)
 		bodyLen += ext.Len(proto)
 	}
 	}
 	if bodyLen > 0 {
 	if bodyLen > 0 {
-		dataLen = multipartMessageOrigDatagramLen(proto, b)
+		if withOrigDgram {
+			dataLen = multipartMessageOrigDatagramLen(proto, b)
+		}
 		bodyLen += 4 // length of extension header
 		bodyLen += 4 // length of extension header
 	} else {
 	} else {
 		dataLen = len(b)
 		dataLen = len(b)
@@ -50,8 +52,8 @@ func multipartMessageOrigDatagramLen(proto int, b []byte) int {
 // marshalMultipartMessageBody takes data as an original datagram and
 // marshalMultipartMessageBody takes data as an original datagram and
 // exts as extesnsions, and returns a binary encoding of message body.
 // exts as extesnsions, and returns a binary encoding of message body.
 // It can be used for non-multipart message bodies when exts is nil.
 // It can be used for non-multipart message bodies when exts is nil.
-func marshalMultipartMessageBody(proto int, data []byte, exts []Extension) ([]byte, error) {
-	bodyLen, dataLen := multipartMessageBodyDataLen(proto, data, exts)
+func marshalMultipartMessageBody(proto int, withOrigDgram bool, data []byte, exts []Extension) ([]byte, error) {
+	bodyLen, dataLen := multipartMessageBodyDataLen(proto, withOrigDgram, data, exts)
 	b := make([]byte, 4+bodyLen)
 	b := make([]byte, 4+bodyLen)
 	copy(b[4:], data)
 	copy(b[4:], data)
 	off := dataLen + 4
 	off := dataLen + 4
@@ -71,16 +73,23 @@ func marshalMultipartMessageBody(proto int, data []byte, exts []Extension) ([]by
 					return nil, err
 					return nil, err
 				}
 				}
 				off += ext.Len(proto)
 				off += ext.Len(proto)
+			case *InterfaceIdent:
+				if err := ext.marshal(proto, b[off:]); err != nil {
+					return nil, err
+				}
+				off += ext.Len(proto)
 			}
 			}
 		}
 		}
 		s := checksum(b[dataLen+4:])
 		s := checksum(b[dataLen+4:])
 		b[dataLen+4+2] ^= byte(s)
 		b[dataLen+4+2] ^= byte(s)
 		b[dataLen+4+3] ^= byte(s >> 8)
 		b[dataLen+4+3] ^= byte(s >> 8)
-		switch proto {
-		case iana.ProtocolICMP:
-			b[1] = byte(dataLen / 4)
-		case iana.ProtocolIPv6ICMP:
-			b[0] = byte(dataLen / 8)
+		if withOrigDgram {
+			switch proto {
+			case iana.ProtocolICMP:
+				b[1] = byte(dataLen / 4)
+			case iana.ProtocolIPv6ICMP:
+				b[0] = byte(dataLen / 8)
+			}
 		}
 		}
 	}
 	}
 	return b, nil
 	return b, nil
@@ -88,7 +97,7 @@ func marshalMultipartMessageBody(proto int, data []byte, exts []Extension) ([]by
 
 
 // parseMultipartMessageBody parses b as either a non-multipart
 // parseMultipartMessageBody parses b as either a non-multipart
 // message body or a multipart message body.
 // message body or a multipart message body.
-func parseMultipartMessageBody(proto int, b []byte) ([]byte, []Extension, error) {
+func parseMultipartMessageBody(proto int, typ Type, b []byte) ([]byte, []Extension, error) {
 	var l int
 	var l int
 	switch proto {
 	switch proto {
 	case iana.ProtocolICMP:
 	case iana.ProtocolICMP:
@@ -99,11 +108,14 @@ func parseMultipartMessageBody(proto int, b []byte) ([]byte, []Extension, error)
 	if len(b) == 4 {
 	if len(b) == 4 {
 		return nil, nil, nil
 		return nil, nil, nil
 	}
 	}
-	exts, l, err := parseExtensions(b[4:], l)
+	exts, l, err := parseExtensions(typ, b[4:], l)
 	if err != nil {
 	if err != nil {
 		l = len(b) - 4
 		l = len(b) - 4
 	}
 	}
-	data := make([]byte, l)
-	copy(data, b[4:])
+	var data []byte
+	if l > 0 {
+		data = make([]byte, l)
+		copy(data, b[4:])
+	}
 	return data, exts, nil
 	return data, exts, nil
 }
 }

+ 470 - 337
vendor/golang.org/x/net/icmp/multipart_test.go

@@ -5,6 +5,7 @@
 package icmp_test
 package icmp_test
 
 
 import (
 import (
+	"errors"
 	"fmt"
 	"fmt"
 	"net"
 	"net"
 	"reflect"
 	"reflect"
@@ -16,425 +17,557 @@ import (
 	"golang.org/x/net/ipv6"
 	"golang.org/x/net/ipv6"
 )
 )
 
 
-var marshalAndParseMultipartMessageForIPv4Tests = []icmp.Message{
-	{
-		Type: ipv4.ICMPTypeDestinationUnreachable, Code: 15,
-		Body: &icmp.DstUnreach{
-			Data: []byte("ERROR-INVOKING-PACKET"),
-			Extensions: []icmp.Extension{
-				&icmp.MPLSLabelStack{
-					Class: 1,
-					Type:  1,
-					Labels: []icmp.MPLSLabel{
-						{
-							Label: 16014,
-							TC:    0x4,
-							S:     true,
-							TTL:   255,
-						},
-					},
-				},
-				&icmp.InterfaceInfo{
-					Class: 2,
-					Type:  0x0f,
-					Interface: &net.Interface{
-						Index: 15,
-						Name:  "en101",
-						MTU:   8192,
-					},
-					Addr: &net.IPAddr{
-						IP: net.IPv4(192, 168, 0, 1).To4(),
-					},
-				},
-			},
-		},
-	},
-	{
-		Type: ipv4.ICMPTypeTimeExceeded, Code: 1,
-		Body: &icmp.TimeExceeded{
-			Data: []byte("ERROR-INVOKING-PACKET"),
-			Extensions: []icmp.Extension{
-				&icmp.InterfaceInfo{
-					Class: 2,
-					Type:  0x0f,
-					Interface: &net.Interface{
-						Index: 15,
-						Name:  "en101",
-						MTU:   8192,
-					},
-					Addr: &net.IPAddr{
-						IP: net.IPv4(192, 168, 0, 1).To4(),
-					},
-				},
-				&icmp.MPLSLabelStack{
-					Class: 1,
-					Type:  1,
-					Labels: []icmp.MPLSLabel{
-						{
-							Label: 16014,
-							TC:    0x4,
-							S:     true,
-							TTL:   255,
-						},
-					},
-				},
-			},
-		},
-	},
-	{
-		Type: ipv4.ICMPTypeParameterProblem, Code: 2,
-		Body: &icmp.ParamProb{
-			Pointer: 8,
-			Data:    []byte("ERROR-INVOKING-PACKET"),
-			Extensions: []icmp.Extension{
-				&icmp.MPLSLabelStack{
-					Class: 1,
-					Type:  1,
-					Labels: []icmp.MPLSLabel{
-						{
-							Label: 16014,
-							TC:    0x4,
-							S:     true,
-							TTL:   255,
-						},
-					},
-				},
-				&icmp.InterfaceInfo{
-					Class: 2,
-					Type:  0x0f,
-					Interface: &net.Interface{
-						Index: 15,
-						Name:  "en101",
-						MTU:   8192,
-					},
-					Addr: &net.IPAddr{
-						IP: net.IPv4(192, 168, 0, 1).To4(),
-					},
-				},
-				&icmp.InterfaceInfo{
-					Class: 2,
-					Type:  0x2f,
-					Interface: &net.Interface{
-						Index: 16,
-						Name:  "en102",
-						MTU:   8192,
-					},
-					Addr: &net.IPAddr{
-						IP: net.IPv4(192, 168, 0, 2).To4(),
-					},
-				},
-			},
-		},
-	},
-}
-
-func TestMarshalAndParseMultipartMessageForIPv4(t *testing.T) {
-	for i, tt := range marshalAndParseMultipartMessageForIPv4Tests {
-		b, err := tt.Marshal(nil)
+func TestMarshalAndParseMultipartMessage(t *testing.T) {
+	fn := func(t *testing.T, proto int, tm icmp.Message) error {
+		b, err := tm.Marshal(nil)
 		if err != nil {
 		if err != nil {
-			t.Fatal(err)
+			return err
 		}
 		}
-		if b[5] != 32 {
-			t.Errorf("#%v: got %v; want 32", i, b[5])
+		switch tm.Type {
+		case ipv4.ICMPTypeExtendedEchoRequest, ipv6.ICMPTypeExtendedEchoRequest:
+		default:
+			switch proto {
+			case iana.ProtocolICMP:
+				if b[5] != 32 {
+					return fmt.Errorf("got %d; want 32", b[5])
+				}
+			case iana.ProtocolIPv6ICMP:
+				if b[4] != 16 {
+					return fmt.Errorf("got %d; want 16", b[4])
+				}
+			default:
+				return fmt.Errorf("unknown protocol: %d", proto)
+			}
 		}
 		}
-		m, err := icmp.ParseMessage(iana.ProtocolICMP, b)
+		m, err := icmp.ParseMessage(proto, b)
 		if err != nil {
 		if err != nil {
-			t.Fatal(err)
+			return err
 		}
 		}
-		if m.Type != tt.Type || m.Code != tt.Code {
-			t.Errorf("#%v: got %v; want %v", i, m, &tt)
+		if m.Type != tm.Type || m.Code != tm.Code {
+			return fmt.Errorf("got %v; want %v", m, &tm)
 		}
 		}
 		switch m.Type {
 		switch m.Type {
+		case ipv4.ICMPTypeExtendedEchoRequest, ipv6.ICMPTypeExtendedEchoRequest:
+			got, want := m.Body.(*icmp.ExtendedEchoRequest), tm.Body.(*icmp.ExtendedEchoRequest)
+			if !reflect.DeepEqual(got.Extensions, want.Extensions) {
+				return errors.New(dumpExtensions(got.Extensions, want.Extensions))
+			}
 		case ipv4.ICMPTypeDestinationUnreachable:
 		case ipv4.ICMPTypeDestinationUnreachable:
-			got, want := m.Body.(*icmp.DstUnreach), tt.Body.(*icmp.DstUnreach)
+			got, want := m.Body.(*icmp.DstUnreach), tm.Body.(*icmp.DstUnreach)
 			if !reflect.DeepEqual(got.Extensions, want.Extensions) {
 			if !reflect.DeepEqual(got.Extensions, want.Extensions) {
-				t.Error(dumpExtensions(i, got.Extensions, want.Extensions))
+				return errors.New(dumpExtensions(got.Extensions, want.Extensions))
 			}
 			}
 			if len(got.Data) != 128 {
 			if len(got.Data) != 128 {
-				t.Errorf("#%v: got %v; want 128", i, len(got.Data))
+				return fmt.Errorf("got %d; want 128", len(got.Data))
 			}
 			}
 		case ipv4.ICMPTypeTimeExceeded:
 		case ipv4.ICMPTypeTimeExceeded:
-			got, want := m.Body.(*icmp.TimeExceeded), tt.Body.(*icmp.TimeExceeded)
+			got, want := m.Body.(*icmp.TimeExceeded), tm.Body.(*icmp.TimeExceeded)
 			if !reflect.DeepEqual(got.Extensions, want.Extensions) {
 			if !reflect.DeepEqual(got.Extensions, want.Extensions) {
-				t.Error(dumpExtensions(i, got.Extensions, want.Extensions))
+				return errors.New(dumpExtensions(got.Extensions, want.Extensions))
 			}
 			}
 			if len(got.Data) != 128 {
 			if len(got.Data) != 128 {
-				t.Errorf("#%v: got %v; want 128", i, len(got.Data))
+				return fmt.Errorf("got %d; want 128", len(got.Data))
 			}
 			}
 		case ipv4.ICMPTypeParameterProblem:
 		case ipv4.ICMPTypeParameterProblem:
-			got, want := m.Body.(*icmp.ParamProb), tt.Body.(*icmp.ParamProb)
+			got, want := m.Body.(*icmp.ParamProb), tm.Body.(*icmp.ParamProb)
+			if !reflect.DeepEqual(got.Extensions, want.Extensions) {
+				return errors.New(dumpExtensions(got.Extensions, want.Extensions))
+			}
+			if len(got.Data) != 128 {
+				return fmt.Errorf("got %d; want 128", len(got.Data))
+			}
+		case ipv6.ICMPTypeDestinationUnreachable:
+			got, want := m.Body.(*icmp.DstUnreach), tm.Body.(*icmp.DstUnreach)
 			if !reflect.DeepEqual(got.Extensions, want.Extensions) {
 			if !reflect.DeepEqual(got.Extensions, want.Extensions) {
-				t.Error(dumpExtensions(i, got.Extensions, want.Extensions))
+				return errors.New(dumpExtensions(got.Extensions, want.Extensions))
 			}
 			}
 			if len(got.Data) != 128 {
 			if len(got.Data) != 128 {
-				t.Errorf("#%v: got %v; want 128", i, len(got.Data))
+				return fmt.Errorf("got %d; want 128", len(got.Data))
 			}
 			}
+		case ipv6.ICMPTypeTimeExceeded:
+			got, want := m.Body.(*icmp.TimeExceeded), tm.Body.(*icmp.TimeExceeded)
+			if !reflect.DeepEqual(got.Extensions, want.Extensions) {
+				return errors.New(dumpExtensions(got.Extensions, want.Extensions))
+			}
+			if len(got.Data) != 128 {
+				return fmt.Errorf("got %d; want 128", len(got.Data))
+			}
+		default:
+			return fmt.Errorf("unknown message type: %v", m.Type)
 		}
 		}
+		return nil
 	}
 	}
-}
 
 
-var marshalAndParseMultipartMessageForIPv6Tests = []icmp.Message{
-	{
-		Type: ipv6.ICMPTypeDestinationUnreachable, Code: 6,
-		Body: &icmp.DstUnreach{
-			Data: []byte("ERROR-INVOKING-PACKET"),
-			Extensions: []icmp.Extension{
-				&icmp.MPLSLabelStack{
-					Class: 1,
-					Type:  1,
-					Labels: []icmp.MPLSLabel{
-						{
-							Label: 16014,
-							TC:    0x4,
-							S:     true,
-							TTL:   255,
+	t.Run("IPv4", func(t *testing.T) {
+		for i, tm := range []icmp.Message{
+			{
+				Type: ipv4.ICMPTypeDestinationUnreachable, Code: 15,
+				Body: &icmp.DstUnreach{
+					Data: []byte("ERROR-INVOKING-PACKET"),
+					Extensions: []icmp.Extension{
+						&icmp.MPLSLabelStack{
+							Class: 1,
+							Type:  1,
+							Labels: []icmp.MPLSLabel{
+								{
+									Label: 16014,
+									TC:    0x4,
+									S:     true,
+									TTL:   255,
+								},
+							},
+						},
+						&icmp.InterfaceInfo{
+							Class: 2,
+							Type:  0x0f,
+							Interface: &net.Interface{
+								Index: 15,
+								Name:  "en101",
+								MTU:   8192,
+							},
+							Addr: &net.IPAddr{
+								IP: net.IPv4(192, 168, 0, 1).To4(),
+							},
 						},
 						},
 					},
 					},
 				},
 				},
-				&icmp.InterfaceInfo{
-					Class: 2,
-					Type:  0x0f,
-					Interface: &net.Interface{
-						Index: 15,
-						Name:  "en101",
-						MTU:   8192,
+			},
+			{
+				Type: ipv4.ICMPTypeTimeExceeded, Code: 1,
+				Body: &icmp.TimeExceeded{
+					Data: []byte("ERROR-INVOKING-PACKET"),
+					Extensions: []icmp.Extension{
+						&icmp.InterfaceInfo{
+							Class: 2,
+							Type:  0x0f,
+							Interface: &net.Interface{
+								Index: 15,
+								Name:  "en101",
+								MTU:   8192,
+							},
+							Addr: &net.IPAddr{
+								IP: net.IPv4(192, 168, 0, 1).To4(),
+							},
+						},
+						&icmp.MPLSLabelStack{
+							Class: 1,
+							Type:  1,
+							Labels: []icmp.MPLSLabel{
+								{
+									Label: 16014,
+									TC:    0x4,
+									S:     true,
+									TTL:   255,
+								},
+							},
+						},
 					},
 					},
-					Addr: &net.IPAddr{
-						IP:   net.ParseIP("fe80::1"),
-						Zone: "en101",
+				},
+			},
+			{
+				Type: ipv4.ICMPTypeParameterProblem, Code: 2,
+				Body: &icmp.ParamProb{
+					Pointer: 8,
+					Data:    []byte("ERROR-INVOKING-PACKET"),
+					Extensions: []icmp.Extension{
+						&icmp.MPLSLabelStack{
+							Class: 1,
+							Type:  1,
+							Labels: []icmp.MPLSLabel{
+								{
+									Label: 16014,
+									TC:    0x4,
+									S:     true,
+									TTL:   255,
+								},
+							},
+						},
+						&icmp.InterfaceInfo{
+							Class: 2,
+							Type:  0x0f,
+							Interface: &net.Interface{
+								Index: 15,
+								Name:  "en101",
+								MTU:   8192,
+							},
+							Addr: &net.IPAddr{
+								IP: net.IPv4(192, 168, 0, 1).To4(),
+							},
+						},
+						&icmp.InterfaceInfo{
+							Class: 2,
+							Type:  0x2f,
+							Interface: &net.Interface{
+								Index: 16,
+								Name:  "en102",
+								MTU:   8192,
+							},
+							Addr: &net.IPAddr{
+								IP: net.IPv4(192, 168, 0, 2).To4(),
+							},
+						},
 					},
 					},
 				},
 				},
 			},
 			},
-		},
-	},
-	{
-		Type: ipv6.ICMPTypeTimeExceeded, Code: 1,
-		Body: &icmp.TimeExceeded{
-			Data: []byte("ERROR-INVOKING-PACKET"),
-			Extensions: []icmp.Extension{
-				&icmp.InterfaceInfo{
-					Class: 2,
-					Type:  0x0f,
-					Interface: &net.Interface{
-						Index: 15,
-						Name:  "en101",
-						MTU:   8192,
+			{
+				Type: ipv4.ICMPTypeExtendedEchoRequest, Code: 0,
+				Body: &icmp.ExtendedEchoRequest{
+					ID: 1, Seq: 2, Local: true,
+					Extensions: []icmp.Extension{
+						&icmp.InterfaceIdent{
+							Class: 3,
+							Type:  1,
+							Name:  "en101",
+						},
 					},
 					},
-					Addr: &net.IPAddr{
-						IP:   net.ParseIP("fe80::1"),
-						Zone: "en101",
+				},
+			},
+			{
+				Type: ipv4.ICMPTypeExtendedEchoRequest, Code: 0,
+				Body: &icmp.ExtendedEchoRequest{
+					ID: 1, Seq: 2, Local: true,
+					Extensions: []icmp.Extension{
+						&icmp.InterfaceIdent{
+							Class: 3,
+							Type:  2,
+							Index: 911,
+						},
+						&icmp.InterfaceIdent{
+							Class: 3,
+							Type:  1,
+							Name:  "en101",
+						},
 					},
 					},
 				},
 				},
-				&icmp.MPLSLabelStack{
-					Class: 1,
-					Type:  1,
-					Labels: []icmp.MPLSLabel{
-						{
-							Label: 16014,
-							TC:    0x4,
-							S:     true,
-							TTL:   255,
+			},
+			{
+				Type: ipv4.ICMPTypeExtendedEchoRequest, Code: 0,
+				Body: &icmp.ExtendedEchoRequest{
+					ID: 1, Seq: 2,
+					Extensions: []icmp.Extension{
+						&icmp.InterfaceIdent{
+							Class: 3,
+							Type:  3,
+							AFI:   iana.AddrFamily48bitMAC,
+							Addr:  []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab},
 						},
 						},
 					},
 					},
 				},
 				},
-				&icmp.InterfaceInfo{
-					Class: 2,
-					Type:  0x2f,
-					Interface: &net.Interface{
-						Index: 16,
-						Name:  "en102",
-						MTU:   8192,
+			},
+		} {
+			if err := fn(t, iana.ProtocolICMP, tm); err != nil {
+				t.Errorf("#%d: %v", i, err)
+			}
+		}
+	})
+	t.Run("IPv6", func(t *testing.T) {
+		for i, tm := range []icmp.Message{
+			{
+				Type: ipv6.ICMPTypeDestinationUnreachable, Code: 6,
+				Body: &icmp.DstUnreach{
+					Data: []byte("ERROR-INVOKING-PACKET"),
+					Extensions: []icmp.Extension{
+						&icmp.MPLSLabelStack{
+							Class: 1,
+							Type:  1,
+							Labels: []icmp.MPLSLabel{
+								{
+									Label: 16014,
+									TC:    0x4,
+									S:     true,
+									TTL:   255,
+								},
+							},
+						},
+						&icmp.InterfaceInfo{
+							Class: 2,
+							Type:  0x0f,
+							Interface: &net.Interface{
+								Index: 15,
+								Name:  "en101",
+								MTU:   8192,
+							},
+							Addr: &net.IPAddr{
+								IP:   net.ParseIP("fe80::1"),
+								Zone: "en101",
+							},
+						},
 					},
 					},
-					Addr: &net.IPAddr{
-						IP:   net.ParseIP("fe80::1"),
-						Zone: "en102",
+				},
+			},
+			{
+				Type: ipv6.ICMPTypeTimeExceeded, Code: 1,
+				Body: &icmp.TimeExceeded{
+					Data: []byte("ERROR-INVOKING-PACKET"),
+					Extensions: []icmp.Extension{
+						&icmp.InterfaceInfo{
+							Class: 2,
+							Type:  0x0f,
+							Interface: &net.Interface{
+								Index: 15,
+								Name:  "en101",
+								MTU:   8192,
+							},
+							Addr: &net.IPAddr{
+								IP:   net.ParseIP("fe80::1"),
+								Zone: "en101",
+							},
+						},
+						&icmp.MPLSLabelStack{
+							Class: 1,
+							Type:  1,
+							Labels: []icmp.MPLSLabel{
+								{
+									Label: 16014,
+									TC:    0x4,
+									S:     true,
+									TTL:   255,
+								},
+							},
+						},
+						&icmp.InterfaceInfo{
+							Class: 2,
+							Type:  0x2f,
+							Interface: &net.Interface{
+								Index: 16,
+								Name:  "en102",
+								MTU:   8192,
+							},
+							Addr: &net.IPAddr{
+								IP:   net.ParseIP("fe80::1"),
+								Zone: "en102",
+							},
+						},
 					},
 					},
 				},
 				},
 			},
 			},
-		},
-	},
-}
-
-func TestMarshalAndParseMultipartMessageForIPv6(t *testing.T) {
-	pshicmp := icmp.IPv6PseudoHeader(net.ParseIP("fe80::1"), net.ParseIP("ff02::1"))
-	for i, tt := range marshalAndParseMultipartMessageForIPv6Tests {
-		for _, psh := range [][]byte{pshicmp, nil} {
-			b, err := tt.Marshal(psh)
-			if err != nil {
-				t.Fatal(err)
-			}
-			if b[4] != 16 {
-				t.Errorf("#%v: got %v; want 16", i, b[4])
-			}
-			m, err := icmp.ParseMessage(iana.ProtocolIPv6ICMP, b)
-			if err != nil {
-				t.Fatal(err)
-			}
-			if m.Type != tt.Type || m.Code != tt.Code {
-				t.Errorf("#%v: got %v; want %v", i, m, &tt)
-			}
-			switch m.Type {
-			case ipv6.ICMPTypeDestinationUnreachable:
-				got, want := m.Body.(*icmp.DstUnreach), tt.Body.(*icmp.DstUnreach)
-				if !reflect.DeepEqual(got.Extensions, want.Extensions) {
-					t.Error(dumpExtensions(i, got.Extensions, want.Extensions))
-				}
-				if len(got.Data) != 128 {
-					t.Errorf("#%v: got %v; want 128", i, len(got.Data))
-				}
-			case ipv6.ICMPTypeTimeExceeded:
-				got, want := m.Body.(*icmp.TimeExceeded), tt.Body.(*icmp.TimeExceeded)
-				if !reflect.DeepEqual(got.Extensions, want.Extensions) {
-					t.Error(dumpExtensions(i, got.Extensions, want.Extensions))
-				}
-				if len(got.Data) != 128 {
-					t.Errorf("#%v: got %v; want 128", i, len(got.Data))
-				}
+			{
+				Type: ipv6.ICMPTypeExtendedEchoRequest, Code: 0,
+				Body: &icmp.ExtendedEchoRequest{
+					ID: 1, Seq: 2, Local: true,
+					Extensions: []icmp.Extension{
+						&icmp.InterfaceIdent{
+							Class: 3,
+							Type:  1,
+							Name:  "en101",
+						},
+					},
+				},
+			},
+			{
+				Type: ipv6.ICMPTypeExtendedEchoRequest, Code: 0,
+				Body: &icmp.ExtendedEchoRequest{
+					ID: 1, Seq: 2, Local: true,
+					Extensions: []icmp.Extension{
+						&icmp.InterfaceIdent{
+							Class: 3,
+							Type:  1,
+							Name:  "en101",
+						},
+						&icmp.InterfaceIdent{
+							Class: 3,
+							Type:  2,
+							Index: 911,
+						},
+					},
+				},
+			},
+			{
+				Type: ipv6.ICMPTypeExtendedEchoRequest, Code: 0,
+				Body: &icmp.ExtendedEchoRequest{
+					ID: 1, Seq: 2,
+					Extensions: []icmp.Extension{
+						&icmp.InterfaceIdent{
+							Class: 3,
+							Type:  3,
+							AFI:   iana.AddrFamilyIPv4,
+							Addr:  []byte{192, 0, 2, 1},
+						},
+					},
+				},
+			},
+		} {
+			if err := fn(t, iana.ProtocolIPv6ICMP, tm); err != nil {
+				t.Errorf("#%d: %v", i, err)
 			}
 			}
 		}
 		}
-	}
+	})
 }
 }
 
 
-func dumpExtensions(i int, gotExts, wantExts []icmp.Extension) string {
+func dumpExtensions(gotExts, wantExts []icmp.Extension) string {
 	var s string
 	var s string
-	for j, got := range gotExts {
+	for i, got := range gotExts {
 		switch got := got.(type) {
 		switch got := got.(type) {
 		case *icmp.MPLSLabelStack:
 		case *icmp.MPLSLabelStack:
-			want := wantExts[j].(*icmp.MPLSLabelStack)
+			want := wantExts[i].(*icmp.MPLSLabelStack)
 			if !reflect.DeepEqual(got, want) {
 			if !reflect.DeepEqual(got, want) {
-				s += fmt.Sprintf("#%v/%v: got %#v; want %#v\n", i, j, got, want)
+				s += fmt.Sprintf("#%d: got %#v; want %#v\n", i, got, want)
 			}
 			}
 		case *icmp.InterfaceInfo:
 		case *icmp.InterfaceInfo:
-			want := wantExts[j].(*icmp.InterfaceInfo)
+			want := wantExts[i].(*icmp.InterfaceInfo)
+			if !reflect.DeepEqual(got, want) {
+				s += fmt.Sprintf("#%d: got %#v, %#v, %#v; want %#v, %#v, %#v\n", i, got, got.Interface, got.Addr, want, want.Interface, want.Addr)
+			}
+		case *icmp.InterfaceIdent:
+			want := wantExts[i].(*icmp.InterfaceIdent)
 			if !reflect.DeepEqual(got, want) {
 			if !reflect.DeepEqual(got, want) {
-				s += fmt.Sprintf("#%v/%v: got %#v, %#v, %#v; want %#v, %#v, %#v\n", i, j, got, got.Interface, got.Addr, want, want.Interface, want.Addr)
+				s += fmt.Sprintf("#%d: got %#v; want %#v\n", i, got, want)
 			}
 			}
 		}
 		}
 	}
 	}
+	if len(s) == 0 {
+		return "<nil>"
+	}
 	return s[:len(s)-1]
 	return s[:len(s)-1]
 }
 }
 
 
-var multipartMessageBodyLenTests = []struct {
-	proto int
-	in    icmp.MessageBody
-	out   int
-}{
-	{
-		iana.ProtocolICMP,
-		&icmp.DstUnreach{
-			Data: make([]byte, ipv4.HeaderLen),
+func TestMultipartMessageBodyLen(t *testing.T) {
+	for i, tt := range []struct {
+		proto int
+		in    icmp.MessageBody
+		out   int
+	}{
+		{
+			iana.ProtocolICMP,
+			&icmp.DstUnreach{
+				Data: make([]byte, ipv4.HeaderLen),
+			},
+			4 + ipv4.HeaderLen, // unused and original datagram
 		},
 		},
-		4 + ipv4.HeaderLen, // unused and original datagram
-	},
-	{
-		iana.ProtocolICMP,
-		&icmp.TimeExceeded{
-			Data: make([]byte, ipv4.HeaderLen),
+		{
+			iana.ProtocolICMP,
+			&icmp.TimeExceeded{
+				Data: make([]byte, ipv4.HeaderLen),
+			},
+			4 + ipv4.HeaderLen, // unused and original datagram
 		},
 		},
-		4 + ipv4.HeaderLen, // unused and original datagram
-	},
-	{
-		iana.ProtocolICMP,
-		&icmp.ParamProb{
-			Data: make([]byte, ipv4.HeaderLen),
+		{
+			iana.ProtocolICMP,
+			&icmp.ParamProb{
+				Data: make([]byte, ipv4.HeaderLen),
+			},
+			4 + ipv4.HeaderLen, // [pointer, unused] and original datagram
 		},
 		},
-		4 + ipv4.HeaderLen, // [pointer, unused] and original datagram
-	},
 
 
-	{
-		iana.ProtocolICMP,
-		&icmp.ParamProb{
-			Data: make([]byte, ipv4.HeaderLen),
-			Extensions: []icmp.Extension{
-				&icmp.MPLSLabelStack{},
+		{
+			iana.ProtocolICMP,
+			&icmp.ParamProb{
+				Data: make([]byte, ipv4.HeaderLen),
+				Extensions: []icmp.Extension{
+					&icmp.MPLSLabelStack{},
+				},
 			},
 			},
+			4 + 4 + 4 + 0 + 128, // [pointer, length, unused], extension header, object header, object payload, original datagram
 		},
 		},
-		4 + 4 + 4 + 0 + 128, // [pointer, length, unused], extension header, object header, object payload, original datagram
-	},
-	{
-		iana.ProtocolICMP,
-		&icmp.ParamProb{
-			Data: make([]byte, 128),
-			Extensions: []icmp.Extension{
-				&icmp.MPLSLabelStack{},
+		{
+			iana.ProtocolICMP,
+			&icmp.ParamProb{
+				Data: make([]byte, 128),
+				Extensions: []icmp.Extension{
+					&icmp.MPLSLabelStack{},
+				},
 			},
 			},
+			4 + 4 + 4 + 0 + 128, // [pointer, length, unused], extension header, object header, object payload and original datagram
 		},
 		},
-		4 + 4 + 4 + 0 + 128, // [pointer, length, unused], extension header, object header, object payload and original datagram
-	},
-	{
-		iana.ProtocolICMP,
-		&icmp.ParamProb{
-			Data: make([]byte, 129),
-			Extensions: []icmp.Extension{
-				&icmp.MPLSLabelStack{},
+		{
+			iana.ProtocolICMP,
+			&icmp.ParamProb{
+				Data: make([]byte, 129),
+				Extensions: []icmp.Extension{
+					&icmp.MPLSLabelStack{},
+				},
 			},
 			},
+			4 + 4 + 4 + 0 + 132, // [pointer, length, unused], extension header, object header, object payload and original datagram
 		},
 		},
-		4 + 4 + 4 + 0 + 132, // [pointer, length, unused], extension header, object header, object payload and original datagram
-	},
 
 
-	{
-		iana.ProtocolIPv6ICMP,
-		&icmp.DstUnreach{
-			Data: make([]byte, ipv6.HeaderLen),
+		{
+			iana.ProtocolIPv6ICMP,
+			&icmp.DstUnreach{
+				Data: make([]byte, ipv6.HeaderLen),
+			},
+			4 + ipv6.HeaderLen, // unused and original datagram
 		},
 		},
-		4 + ipv6.HeaderLen, // unused and original datagram
-	},
-	{
-		iana.ProtocolIPv6ICMP,
-		&icmp.PacketTooBig{
-			Data: make([]byte, ipv6.HeaderLen),
+		{
+			iana.ProtocolIPv6ICMP,
+			&icmp.PacketTooBig{
+				Data: make([]byte, ipv6.HeaderLen),
+			},
+			4 + ipv6.HeaderLen, // mtu and original datagram
 		},
 		},
-		4 + ipv6.HeaderLen, // mtu and original datagram
-	},
-	{
-		iana.ProtocolIPv6ICMP,
-		&icmp.TimeExceeded{
-			Data: make([]byte, ipv6.HeaderLen),
+		{
+			iana.ProtocolIPv6ICMP,
+			&icmp.TimeExceeded{
+				Data: make([]byte, ipv6.HeaderLen),
+			},
+			4 + ipv6.HeaderLen, // unused and original datagram
 		},
 		},
-		4 + ipv6.HeaderLen, // unused and original datagram
-	},
-	{
-		iana.ProtocolIPv6ICMP,
-		&icmp.ParamProb{
-			Data: make([]byte, ipv6.HeaderLen),
+		{
+			iana.ProtocolIPv6ICMP,
+			&icmp.ParamProb{
+				Data: make([]byte, ipv6.HeaderLen),
+			},
+			4 + ipv6.HeaderLen, // pointer and original datagram
 		},
 		},
-		4 + ipv6.HeaderLen, // pointer and original datagram
-	},
 
 
-	{
-		iana.ProtocolIPv6ICMP,
-		&icmp.DstUnreach{
-			Data: make([]byte, 127),
-			Extensions: []icmp.Extension{
-				&icmp.MPLSLabelStack{},
+		{
+			iana.ProtocolIPv6ICMP,
+			&icmp.DstUnreach{
+				Data: make([]byte, 127),
+				Extensions: []icmp.Extension{
+					&icmp.MPLSLabelStack{},
+				},
 			},
 			},
+			4 + 4 + 4 + 0 + 128, // [length, unused], extension header, object header, object payload and original datagram
 		},
 		},
-		4 + 4 + 4 + 0 + 128, // [length, unused], extension header, object header, object payload and original datagram
-	},
-	{
-		iana.ProtocolIPv6ICMP,
-		&icmp.DstUnreach{
-			Data: make([]byte, 128),
-			Extensions: []icmp.Extension{
-				&icmp.MPLSLabelStack{},
+		{
+			iana.ProtocolIPv6ICMP,
+			&icmp.DstUnreach{
+				Data: make([]byte, 128),
+				Extensions: []icmp.Extension{
+					&icmp.MPLSLabelStack{},
+				},
 			},
 			},
+			4 + 4 + 4 + 0 + 128, // [length, unused], extension header, object header, object payload and original datagram
 		},
 		},
-		4 + 4 + 4 + 0 + 128, // [length, unused], extension header, object header, object payload and original datagram
-	},
-	{
-		iana.ProtocolIPv6ICMP,
-		&icmp.DstUnreach{
-			Data: make([]byte, 129),
-			Extensions: []icmp.Extension{
-				&icmp.MPLSLabelStack{},
+		{
+			iana.ProtocolIPv6ICMP,
+			&icmp.DstUnreach{
+				Data: make([]byte, 129),
+				Extensions: []icmp.Extension{
+					&icmp.MPLSLabelStack{},
+				},
 			},
 			},
+			4 + 4 + 4 + 0 + 136, // [length, unused], extension header, object header, object payload and original datagram
 		},
 		},
-		4 + 4 + 4 + 0 + 136, // [length, unused], extension header, object header, object payload and original datagram
-	},
-}
 
 
-func TestMultipartMessageBodyLen(t *testing.T) {
-	for i, tt := range multipartMessageBodyLenTests {
+		{
+			iana.ProtocolICMP,
+			&icmp.ExtendedEchoRequest{},
+			4, // [id, seq, l-bit]
+		},
+		{
+			iana.ProtocolICMP,
+			&icmp.ExtendedEchoRequest{
+				Extensions: []icmp.Extension{
+					&icmp.InterfaceIdent{},
+				},
+			},
+			4 + 4 + 4, // [id, seq, l-bit], extension header, object header
+		},
+		{
+			iana.ProtocolIPv6ICMP,
+			&icmp.ExtendedEchoRequest{
+				Extensions: []icmp.Extension{
+					&icmp.InterfaceIdent{
+						Type: 3,
+						AFI:  iana.AddrFamilyNSAP,
+						Addr: []byte{0x49, 0x00, 0x01, 0xaa, 0xaa, 0xbb, 0xbb, 0xcc, 0xcc, 0x00},
+					},
+				},
+			},
+			4 + 4 + 4 + 16, // [id, seq, l-bit], extension header, object header, object payload
+		},
+	} {
 		if out := tt.in.Len(tt.proto); out != tt.out {
 		if out := tt.in.Len(tt.proto); out != tt.out {
 			t.Errorf("#%d: got %d; want %d", i, out, tt.out)
 			t.Errorf("#%d: got %d; want %d", i, out, tt.out)
 		}
 		}

+ 1 - 1
vendor/golang.org/x/net/icmp/packettoobig.go

@@ -29,7 +29,7 @@ func (p *PacketTooBig) Marshal(proto int) ([]byte, error) {
 }
 }
 
 
 // parsePacketTooBig parses b as an ICMP packet too big message body.
 // parsePacketTooBig parses b as an ICMP packet too big message body.
-func parsePacketTooBig(proto int, b []byte) (MessageBody, error) {
+func parsePacketTooBig(proto int, _ Type, b []byte) (MessageBody, error) {
 	bodyLen := len(b)
 	bodyLen := len(b)
 	if bodyLen < 4 {
 	if bodyLen < 4 {
 		return nil, errMessageTooShort
 		return nil, errMessageTooShort

+ 4 - 4
vendor/golang.org/x/net/icmp/paramprob.go

@@ -21,7 +21,7 @@ func (p *ParamProb) Len(proto int) int {
 	if p == nil {
 	if p == nil {
 		return 0
 		return 0
 	}
 	}
-	l, _ := multipartMessageBodyDataLen(proto, p.Data, p.Extensions)
+	l, _ := multipartMessageBodyDataLen(proto, true, p.Data, p.Extensions)
 	return 4 + l
 	return 4 + l
 }
 }
 
 
@@ -33,7 +33,7 @@ func (p *ParamProb) Marshal(proto int) ([]byte, error) {
 		copy(b[4:], p.Data)
 		copy(b[4:], p.Data)
 		return b, nil
 		return b, nil
 	}
 	}
-	b, err := marshalMultipartMessageBody(proto, p.Data, p.Extensions)
+	b, err := marshalMultipartMessageBody(proto, true, p.Data, p.Extensions)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
@@ -42,7 +42,7 @@ func (p *ParamProb) Marshal(proto int) ([]byte, error) {
 }
 }
 
 
 // parseParamProb parses b as an ICMP parameter problem message body.
 // parseParamProb parses b as an ICMP parameter problem message body.
-func parseParamProb(proto int, b []byte) (MessageBody, error) {
+func parseParamProb(proto int, typ Type, b []byte) (MessageBody, error) {
 	if len(b) < 4 {
 	if len(b) < 4 {
 		return nil, errMessageTooShort
 		return nil, errMessageTooShort
 	}
 	}
@@ -55,7 +55,7 @@ func parseParamProb(proto int, b []byte) (MessageBody, error) {
 	}
 	}
 	p.Pointer = uintptr(b[0])
 	p.Pointer = uintptr(b[0])
 	var err error
 	var err error
-	p.Data, p.Extensions, err = parseMultipartMessageBody(proto, b)
+	p.Data, p.Extensions, err = parseMultipartMessageBody(proto, typ, b)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}

+ 0 - 200
vendor/golang.org/x/net/icmp/ping_test.go

@@ -1,200 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package icmp_test
-
-import (
-	"errors"
-	"fmt"
-	"net"
-	"os"
-	"runtime"
-	"sync"
-	"testing"
-	"time"
-
-	"golang.org/x/net/icmp"
-	"golang.org/x/net/internal/iana"
-	"golang.org/x/net/internal/nettest"
-	"golang.org/x/net/ipv4"
-	"golang.org/x/net/ipv6"
-)
-
-func googleAddr(c *icmp.PacketConn, protocol int) (net.Addr, error) {
-	const host = "www.google.com"
-	ips, err := net.LookupIP(host)
-	if err != nil {
-		return nil, err
-	}
-	netaddr := func(ip net.IP) (net.Addr, error) {
-		switch c.LocalAddr().(type) {
-		case *net.UDPAddr:
-			return &net.UDPAddr{IP: ip}, nil
-		case *net.IPAddr:
-			return &net.IPAddr{IP: ip}, nil
-		default:
-			return nil, errors.New("neither UDPAddr nor IPAddr")
-		}
-	}
-	for _, ip := range ips {
-		switch protocol {
-		case iana.ProtocolICMP:
-			if ip.To4() != nil {
-				return netaddr(ip)
-			}
-		case iana.ProtocolIPv6ICMP:
-			if ip.To16() != nil && ip.To4() == nil {
-				return netaddr(ip)
-			}
-		}
-	}
-	return nil, errors.New("no A or AAAA record")
-}
-
-type pingTest struct {
-	network, address string
-	protocol         int
-	mtype            icmp.Type
-}
-
-var nonPrivilegedPingTests = []pingTest{
-	{"udp4", "0.0.0.0", iana.ProtocolICMP, ipv4.ICMPTypeEcho},
-
-	{"udp6", "::", iana.ProtocolIPv6ICMP, ipv6.ICMPTypeEchoRequest},
-}
-
-func TestNonPrivilegedPing(t *testing.T) {
-	if testing.Short() {
-		t.Skip("avoid external network")
-	}
-	switch runtime.GOOS {
-	case "darwin":
-	case "linux":
-		t.Log("you may need to adjust the net.ipv4.ping_group_range kernel state")
-	default:
-		t.Skipf("not supported on %s", runtime.GOOS)
-	}
-
-	for i, tt := range nonPrivilegedPingTests {
-		if err := doPing(tt, i); err != nil {
-			t.Error(err)
-		}
-	}
-}
-
-var privilegedPingTests = []pingTest{
-	{"ip4:icmp", "0.0.0.0", iana.ProtocolICMP, ipv4.ICMPTypeEcho},
-
-	{"ip6:ipv6-icmp", "::", iana.ProtocolIPv6ICMP, ipv6.ICMPTypeEchoRequest},
-}
-
-func TestPrivilegedPing(t *testing.T) {
-	if testing.Short() {
-		t.Skip("avoid external network")
-	}
-	if m, ok := nettest.SupportsRawIPSocket(); !ok {
-		t.Skip(m)
-	}
-
-	for i, tt := range privilegedPingTests {
-		if err := doPing(tt, i); err != nil {
-			t.Error(err)
-		}
-	}
-}
-
-func doPing(tt pingTest, seq int) error {
-	c, err := icmp.ListenPacket(tt.network, tt.address)
-	if err != nil {
-		return err
-	}
-	defer c.Close()
-
-	dst, err := googleAddr(c, tt.protocol)
-	if err != nil {
-		return err
-	}
-
-	if tt.network != "udp6" && tt.protocol == iana.ProtocolIPv6ICMP {
-		var f ipv6.ICMPFilter
-		f.SetAll(true)
-		f.Accept(ipv6.ICMPTypeDestinationUnreachable)
-		f.Accept(ipv6.ICMPTypePacketTooBig)
-		f.Accept(ipv6.ICMPTypeTimeExceeded)
-		f.Accept(ipv6.ICMPTypeParameterProblem)
-		f.Accept(ipv6.ICMPTypeEchoReply)
-		if err := c.IPv6PacketConn().SetICMPFilter(&f); err != nil {
-			return err
-		}
-	}
-
-	wm := icmp.Message{
-		Type: tt.mtype, Code: 0,
-		Body: &icmp.Echo{
-			ID: os.Getpid() & 0xffff, Seq: 1 << uint(seq),
-			Data: []byte("HELLO-R-U-THERE"),
-		},
-	}
-	wb, err := wm.Marshal(nil)
-	if err != nil {
-		return err
-	}
-	if n, err := c.WriteTo(wb, dst); err != nil {
-		return err
-	} else if n != len(wb) {
-		return fmt.Errorf("got %v; want %v", n, len(wb))
-	}
-
-	rb := make([]byte, 1500)
-	if err := c.SetReadDeadline(time.Now().Add(3 * time.Second)); err != nil {
-		return err
-	}
-	n, peer, err := c.ReadFrom(rb)
-	if err != nil {
-		return err
-	}
-	rm, err := icmp.ParseMessage(tt.protocol, rb[:n])
-	if err != nil {
-		return err
-	}
-	switch rm.Type {
-	case ipv4.ICMPTypeEchoReply, ipv6.ICMPTypeEchoReply:
-		return nil
-	default:
-		return fmt.Errorf("got %+v from %v; want echo reply", rm, peer)
-	}
-}
-
-func TestConcurrentNonPrivilegedListenPacket(t *testing.T) {
-	if testing.Short() {
-		t.Skip("avoid external network")
-	}
-	switch runtime.GOOS {
-	case "darwin":
-	case "linux":
-		t.Log("you may need to adjust the net.ipv4.ping_group_range kernel state")
-	default:
-		t.Skipf("not supported on %s", runtime.GOOS)
-	}
-
-	network, address := "udp4", "127.0.0.1"
-	if !nettest.SupportsIPv4() {
-		network, address = "udp6", "::1"
-	}
-	const N = 1000
-	var wg sync.WaitGroup
-	wg.Add(N)
-	for i := 0; i < N; i++ {
-		go func() {
-			defer wg.Done()
-			c, err := icmp.ListenPacket(network, address)
-			if err != nil {
-				t.Error(err)
-				return
-			}
-			c.Close()
-		}()
-	}
-	wg.Wait()
-}

+ 4 - 4
vendor/golang.org/x/net/icmp/timeexceeded.go

@@ -15,23 +15,23 @@ func (p *TimeExceeded) Len(proto int) int {
 	if p == nil {
 	if p == nil {
 		return 0
 		return 0
 	}
 	}
-	l, _ := multipartMessageBodyDataLen(proto, p.Data, p.Extensions)
+	l, _ := multipartMessageBodyDataLen(proto, true, p.Data, p.Extensions)
 	return 4 + l
 	return 4 + l
 }
 }
 
 
 // Marshal implements the Marshal method of MessageBody interface.
 // Marshal implements the Marshal method of MessageBody interface.
 func (p *TimeExceeded) Marshal(proto int) ([]byte, error) {
 func (p *TimeExceeded) Marshal(proto int) ([]byte, error) {
-	return marshalMultipartMessageBody(proto, p.Data, p.Extensions)
+	return marshalMultipartMessageBody(proto, true, p.Data, p.Extensions)
 }
 }
 
 
 // parseTimeExceeded parses b as an ICMP time exceeded message body.
 // parseTimeExceeded parses b as an ICMP time exceeded message body.
-func parseTimeExceeded(proto int, b []byte) (MessageBody, error) {
+func parseTimeExceeded(proto int, typ Type, b []byte) (MessageBody, error) {
 	if len(b) < 4 {
 	if len(b) < 4 {
 		return nil, errMessageTooShort
 		return nil, errMessageTooShort
 	}
 	}
 	p := &TimeExceeded{}
 	p := &TimeExceeded{}
 	var err error
 	var err error
-	p.Data, p.Extensions, err = parseMultipartMessageBody(proto, b)
+	p.Data, p.Extensions, err = parseMultipartMessageBody(proto, typ, b)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}

+ 6 - 1
vendor/golang.org/x/net/idna/example_test.go

@@ -51,6 +51,10 @@ func ExampleNew() {
 		idna.Transitional(true)) // Map ß -> ss
 		idna.Transitional(true)) // Map ß -> ss
 	fmt.Println(p.ToASCII("*.faß.com"))
 	fmt.Println(p.ToASCII("*.faß.com"))
 
 
+	// Lookup for registration. Also does not allow '*'.
+	p = idna.New(idna.ValidateForRegistration())
+	fmt.Println(p.ToUnicode("*.faß.com"))
+
 	// Set up a profile maps for lookup, but allows wild cards.
 	// Set up a profile maps for lookup, but allows wild cards.
 	p = idna.New(
 	p = idna.New(
 		idna.MapForLookup(),
 		idna.MapForLookup(),
@@ -60,6 +64,7 @@ func ExampleNew() {
 
 
 	// Output:
 	// Output:
 	// *.xn--fa-hia.com <nil>
 	// *.xn--fa-hia.com <nil>
-	// *.fass.com idna: disallowed rune U+002E
+	// *.fass.com idna: disallowed rune U+002A
+	// *.faß.com idna: disallowed rune U+002A
 	// *.fass.com <nil>
 	// *.fass.com <nil>
 }
 }

+ 95 - 31
vendor/golang.org/x/net/idna/idna.go

@@ -21,6 +21,7 @@ import (
 	"unicode/utf8"
 	"unicode/utf8"
 
 
 	"golang.org/x/text/secure/bidirule"
 	"golang.org/x/text/secure/bidirule"
+	"golang.org/x/text/unicode/bidi"
 	"golang.org/x/text/unicode/norm"
 	"golang.org/x/text/unicode/norm"
 )
 )
 
 
@@ -67,6 +68,15 @@ func VerifyDNSLength(verify bool) Option {
 	return func(o *options) { o.verifyDNSLength = verify }
 	return func(o *options) { o.verifyDNSLength = verify }
 }
 }
 
 
+// RemoveLeadingDots removes leading label separators. Leading runes that map to
+// dots, such as U+3002 IDEOGRAPHIC FULL STOP, are removed as well.
+//
+// This is the behavior suggested by the UTS #46 and is adopted by some
+// browsers.
+func RemoveLeadingDots(remove bool) Option {
+	return func(o *options) { o.removeLeadingDots = remove }
+}
+
 // ValidateLabels sets whether to check the mandatory label validation criteria
 // ValidateLabels sets whether to check the mandatory label validation criteria
 // as defined in Section 5.4 of RFC 5891. This includes testing for correct use
 // as defined in Section 5.4 of RFC 5891. This includes testing for correct use
 // of hyphens ('-'), normalization, validity of runes, and the context rules.
 // of hyphens ('-'), normalization, validity of runes, and the context rules.
@@ -83,7 +93,7 @@ func ValidateLabels(enable bool) Option {
 	}
 	}
 }
 }
 
 
-// StrictDomainName limits the set of permissable ASCII characters to those
+// StrictDomainName limits the set of permissible ASCII characters to those
 // allowed in domain names as defined in RFC 1034 (A-Z, a-z, 0-9 and the
 // allowed in domain names as defined in RFC 1034 (A-Z, a-z, 0-9 and the
 // hyphen). This is set by default for MapForLookup and ValidateForRegistration.
 // hyphen). This is set by default for MapForLookup and ValidateForRegistration.
 //
 //
@@ -137,10 +147,11 @@ func MapForLookup() Option {
 }
 }
 
 
 type options struct {
 type options struct {
-	transitional    bool
-	useSTD3Rules    bool
-	validateLabels  bool
-	verifyDNSLength bool
+	transitional      bool
+	useSTD3Rules      bool
+	validateLabels    bool
+	verifyDNSLength   bool
+	removeLeadingDots bool
 
 
 	trie *idnaTrie
 	trie *idnaTrie
 
 
@@ -149,14 +160,14 @@ type options struct {
 
 
 	// mapping implements a validation and mapping step as defined in RFC 5895
 	// mapping implements a validation and mapping step as defined in RFC 5895
 	// or UTS 46, tailored to, for example, domain registration or lookup.
 	// or UTS 46, tailored to, for example, domain registration or lookup.
-	mapping func(p *Profile, s string) (string, error)
+	mapping func(p *Profile, s string) (mapped string, isBidi bool, err error)
 
 
 	// bidirule, if specified, checks whether s conforms to the Bidi Rule
 	// bidirule, if specified, checks whether s conforms to the Bidi Rule
 	// defined in RFC 5893.
 	// defined in RFC 5893.
 	bidirule func(s string) bool
 	bidirule func(s string) bool
 }
 }
 
 
-// A Profile defines the configuration of a IDNA mapper.
+// A Profile defines the configuration of an IDNA mapper.
 type Profile struct {
 type Profile struct {
 	options
 	options
 }
 }
@@ -289,12 +300,16 @@ func (e runeError) Error() string {
 // see http://www.unicode.org/reports/tr46.
 // see http://www.unicode.org/reports/tr46.
 func (p *Profile) process(s string, toASCII bool) (string, error) {
 func (p *Profile) process(s string, toASCII bool) (string, error) {
 	var err error
 	var err error
+	var isBidi bool
 	if p.mapping != nil {
 	if p.mapping != nil {
-		s, err = p.mapping(p, s)
+		s, isBidi, err = p.mapping(p, s)
 	}
 	}
 	// Remove leading empty labels.
 	// Remove leading empty labels.
-	for ; len(s) > 0 && s[0] == '.'; s = s[1:] {
+	if p.removeLeadingDots {
+		for ; len(s) > 0 && s[0] == '.'; s = s[1:] {
+		}
 	}
 	}
+	// TODO: allow for a quick check of the tables data.
 	// It seems like we should only create this error on ToASCII, but the
 	// It seems like we should only create this error on ToASCII, but the
 	// UTS 46 conformance tests suggests we should always check this.
 	// UTS 46 conformance tests suggests we should always check this.
 	if err == nil && p.verifyDNSLength && s == "" {
 	if err == nil && p.verifyDNSLength && s == "" {
@@ -320,6 +335,7 @@ func (p *Profile) process(s string, toASCII bool) (string, error) {
 				// Spec says keep the old label.
 				// Spec says keep the old label.
 				continue
 				continue
 			}
 			}
+			isBidi = isBidi || bidirule.DirectionString(u) != bidi.LeftToRight
 			labels.set(u)
 			labels.set(u)
 			if err == nil && p.validateLabels {
 			if err == nil && p.validateLabels {
 				err = p.fromPuny(p, u)
 				err = p.fromPuny(p, u)
@@ -334,6 +350,14 @@ func (p *Profile) process(s string, toASCII bool) (string, error) {
 			err = p.validateLabel(label)
 			err = p.validateLabel(label)
 		}
 		}
 	}
 	}
+	if isBidi && p.bidirule != nil && err == nil {
+		for labels.reset(); !labels.done(); labels.next() {
+			if !p.bidirule(labels.label()) {
+				err = &labelError{s, "B"}
+				break
+			}
+		}
+	}
 	if toASCII {
 	if toASCII {
 		for labels.reset(); !labels.done(); labels.next() {
 		for labels.reset(); !labels.done(); labels.next() {
 			label := labels.label()
 			label := labels.label()
@@ -365,41 +389,77 @@ func (p *Profile) process(s string, toASCII bool) (string, error) {
 	return s, err
 	return s, err
 }
 }
 
 
-func normalize(p *Profile, s string) (string, error) {
-	return norm.NFC.String(s), nil
+func normalize(p *Profile, s string) (mapped string, isBidi bool, err error) {
+	// TODO: consider first doing a quick check to see if any of these checks
+	// need to be done. This will make it slower in the general case, but
+	// faster in the common case.
+	mapped = norm.NFC.String(s)
+	isBidi = bidirule.DirectionString(mapped) == bidi.RightToLeft
+	return mapped, isBidi, nil
 }
 }
 
 
-func validateRegistration(p *Profile, s string) (string, error) {
+func validateRegistration(p *Profile, s string) (idem string, bidi bool, err error) {
+	// TODO: filter need for normalization in loop below.
 	if !norm.NFC.IsNormalString(s) {
 	if !norm.NFC.IsNormalString(s) {
-		return s, &labelError{s, "V1"}
+		return s, false, &labelError{s, "V1"}
 	}
 	}
-	var err error
 	for i := 0; i < len(s); {
 	for i := 0; i < len(s); {
 		v, sz := trie.lookupString(s[i:])
 		v, sz := trie.lookupString(s[i:])
-		i += sz
+		if sz == 0 {
+			return s, bidi, runeError(utf8.RuneError)
+		}
+		bidi = bidi || info(v).isBidi(s[i:])
 		// Copy bytes not copied so far.
 		// Copy bytes not copied so far.
 		switch p.simplify(info(v).category()) {
 		switch p.simplify(info(v).category()) {
 		// TODO: handle the NV8 defined in the Unicode idna data set to allow
 		// TODO: handle the NV8 defined in the Unicode idna data set to allow
 		// for strict conformance to IDNA2008.
 		// for strict conformance to IDNA2008.
 		case valid, deviation:
 		case valid, deviation:
 		case disallowed, mapped, unknown, ignored:
 		case disallowed, mapped, unknown, ignored:
-			if err == nil {
-				r, _ := utf8.DecodeRuneInString(s[i:])
-				err = runeError(r)
-			}
+			r, _ := utf8.DecodeRuneInString(s[i:])
+			return s, bidi, runeError(r)
 		}
 		}
+		i += sz
 	}
 	}
-	return s, err
+	return s, bidi, nil
 }
 }
 
 
-func validateAndMap(p *Profile, s string) (string, error) {
+func (c info) isBidi(s string) bool {
+	if !c.isMapped() {
+		return c&attributesMask == rtl
+	}
+	// TODO: also store bidi info for mapped data. This is possible, but a bit
+	// cumbersome and not for the common case.
+	p, _ := bidi.LookupString(s)
+	switch p.Class() {
+	case bidi.R, bidi.AL, bidi.AN:
+		return true
+	}
+	return false
+}
+
+func validateAndMap(p *Profile, s string) (vm string, bidi bool, err error) {
 	var (
 	var (
-		err error
-		b   []byte
-		k   int
+		b []byte
+		k int
 	)
 	)
+	// combinedInfoBits contains the or-ed bits of all runes. We use this
+	// to derive the mayNeedNorm bit later. This may trigger normalization
+	// overeagerly, but it will not do so in the common case. The end result
+	// is another 10% saving on BenchmarkProfile for the common case.
+	var combinedInfoBits info
 	for i := 0; i < len(s); {
 	for i := 0; i < len(s); {
 		v, sz := trie.lookupString(s[i:])
 		v, sz := trie.lookupString(s[i:])
+		if sz == 0 {
+			b = append(b, s[k:i]...)
+			b = append(b, "\ufffd"...)
+			k = len(s)
+			if err == nil {
+				err = runeError(utf8.RuneError)
+			}
+			break
+		}
+		combinedInfoBits |= info(v)
+		bidi = bidi || info(v).isBidi(s[i:])
 		start := i
 		start := i
 		i += sz
 		i += sz
 		// Copy bytes not copied so far.
 		// Copy bytes not copied so far.
@@ -408,7 +468,7 @@ func validateAndMap(p *Profile, s string) (string, error) {
 			continue
 			continue
 		case disallowed:
 		case disallowed:
 			if err == nil {
 			if err == nil {
-				r, _ := utf8.DecodeRuneInString(s[i:])
+				r, _ := utf8.DecodeRuneInString(s[start:])
 				err = runeError(r)
 				err = runeError(r)
 			}
 			}
 			continue
 			continue
@@ -426,7 +486,9 @@ func validateAndMap(p *Profile, s string) (string, error) {
 	}
 	}
 	if k == 0 {
 	if k == 0 {
 		// No changes so far.
 		// No changes so far.
-		s = norm.NFC.String(s)
+		if combinedInfoBits&mayNeedNorm != 0 {
+			s = norm.NFC.String(s)
+		}
 	} else {
 	} else {
 		b = append(b, s[k:]...)
 		b = append(b, s[k:]...)
 		if norm.NFC.QuickSpan(b) != len(b) {
 		if norm.NFC.QuickSpan(b) != len(b) {
@@ -435,7 +497,7 @@ func validateAndMap(p *Profile, s string) (string, error) {
 		// TODO: the punycode converters require strings as input.
 		// TODO: the punycode converters require strings as input.
 		s = string(b)
 		s = string(b)
 	}
 	}
-	return s, err
+	return s, bidi, err
 }
 }
 
 
 // A labelIter allows iterating over domain name labels.
 // A labelIter allows iterating over domain name labels.
@@ -530,8 +592,13 @@ func validateFromPunycode(p *Profile, s string) error {
 	if !norm.NFC.IsNormalString(s) {
 	if !norm.NFC.IsNormalString(s) {
 		return &labelError{s, "V1"}
 		return &labelError{s, "V1"}
 	}
 	}
+	// TODO: detect whether string may have to be normalized in the following
+	// loop.
 	for i := 0; i < len(s); {
 	for i := 0; i < len(s); {
 		v, sz := trie.lookupString(s[i:])
 		v, sz := trie.lookupString(s[i:])
+		if sz == 0 {
+			return runeError(utf8.RuneError)
+		}
 		if c := p.simplify(info(v).category()); c != valid && c != deviation {
 		if c := p.simplify(info(v).category()); c != valid && c != deviation {
 			return &labelError{s, "V6"}
 			return &labelError{s, "V6"}
 		}
 		}
@@ -604,16 +671,13 @@ var joinStates = [][numJoinTypes]joinState{
 
 
 // validateLabel validates the criteria from Section 4.1. Item 1, 4, and 6 are
 // validateLabel validates the criteria from Section 4.1. Item 1, 4, and 6 are
 // already implicitly satisfied by the overall implementation.
 // already implicitly satisfied by the overall implementation.
-func (p *Profile) validateLabel(s string) error {
+func (p *Profile) validateLabel(s string) (err error) {
 	if s == "" {
 	if s == "" {
 		if p.verifyDNSLength {
 		if p.verifyDNSLength {
 			return &labelError{s, "A4"}
 			return &labelError{s, "A4"}
 		}
 		}
 		return nil
 		return nil
 	}
 	}
-	if p.bidirule != nil && !p.bidirule(s) {
-		return &labelError{s, "B"}
-	}
 	if !p.validateLabels {
 	if !p.validateLabels {
 		return nil
 		return nil
 	}
 	}

+ 65 - 0
vendor/golang.org/x/net/idna/idna_test.go

@@ -39,5 +39,70 @@ func TestIDNA(t *testing.T) {
 	}
 	}
 }
 }
 
 
+func TestIDNASeparators(t *testing.T) {
+	type subCase struct {
+		unicode   string
+		wantASCII string
+		wantErr   bool
+	}
+
+	testCases := []struct {
+		name     string
+		profile  *Profile
+		subCases []subCase
+	}{
+		{
+			name: "Punycode", profile: Punycode,
+			subCases: []subCase{
+				{"example\u3002jp", "xn--examplejp-ck3h", false},
+				{"東京\uFF0Ejp", "xn--jp-l92cn98g071o", false},
+				{"大阪\uFF61jp", "xn--jp-ku9cz72u463f", false},
+			},
+		},
+		{
+			name: "Lookup", profile: Lookup,
+			subCases: []subCase{
+				{"example\u3002jp", "example.jp", false},
+				{"東京\uFF0Ejp", "xn--1lqs71d.jp", false},
+				{"大阪\uFF61jp", "xn--pssu33l.jp", false},
+			},
+		},
+		{
+			name: "Display", profile: Display,
+			subCases: []subCase{
+				{"example\u3002jp", "example.jp", false},
+				{"東京\uFF0Ejp", "xn--1lqs71d.jp", false},
+				{"大阪\uFF61jp", "xn--pssu33l.jp", false},
+			},
+		},
+		{
+			name: "Registration", profile: Registration,
+			subCases: []subCase{
+				{"example\u3002jp", "", true},
+				{"東京\uFF0Ejp", "", true},
+				{"大阪\uFF61jp", "", true},
+			},
+		},
+	}
+	for _, tc := range testCases {
+		t.Run(tc.name, func(t *testing.T) {
+			for _, c := range tc.subCases {
+				gotA, err := tc.profile.ToASCII(c.unicode)
+				if c.wantErr {
+					if err == nil {
+						t.Errorf("ToASCII(%q): got no error, but an error expected", c.unicode)
+					}
+				} else {
+					if err != nil {
+						t.Errorf("ToASCII(%q): got err=%v, but no error expected", c.unicode, err)
+					} else if gotA != c.wantASCII {
+						t.Errorf("ToASCII(%q): got %q, want %q", c.unicode, gotA, c.wantASCII)
+					}
+				}
+			}
+		})
+	}
+}
+
 // TODO(nigeltao): test errors, once we've specified when ToASCII and ToUnicode
 // TODO(nigeltao): test errors, once we've specified when ToASCII and ToUnicode
 // return errors.
 // return errors.

File diff suppressed because it is too large
+ 1417 - 1384
vendor/golang.org/x/net/idna/tables.go


+ 11 - 6
vendor/golang.org/x/net/idna/trieval.go

@@ -26,9 +26,9 @@ package idna
 //       15..3  index into xor or mapping table
 //       15..3  index into xor or mapping table
 //     }
 //     }
 //   } else {
 //   } else {
-//       15..13 unused
-//           12 modifier (including virama)
-//           11 virama modifier
+//       15..14 unused
+//       13     mayNeedNorm
+//       12..11 attributes
 //       10..8  joining type
 //       10..8  joining type
 //        7..3  category type
 //        7..3  category type
 //   }
 //   }
@@ -49,15 +49,20 @@ const (
 	joinShift = 8
 	joinShift = 8
 	joinMask  = 0x07
 	joinMask  = 0x07
 
 
-	viramaModifier = 0x0800
+	// Attributes
+	attributesMask = 0x1800
+	viramaModifier = 0x1800
 	modifier       = 0x1000
 	modifier       = 0x1000
+	rtl            = 0x0800
+
+	mayNeedNorm = 0x2000
 )
 )
 
 
 // A category corresponds to a category defined in the IDNA mapping table.
 // A category corresponds to a category defined in the IDNA mapping table.
 type category uint16
 type category uint16
 
 
 const (
 const (
-	unknown              category = 0 // not defined currently in unicode.
+	unknown              category = 0 // not currently defined in unicode.
 	mapped               category = 1
 	mapped               category = 1
 	disallowedSTD3Mapped category = 2
 	disallowedSTD3Mapped category = 2
 	deviation            category = 3
 	deviation            category = 3
@@ -110,5 +115,5 @@ func (c info) isModifier() bool {
 }
 }
 
 
 func (c info) isViramaModifier() bool {
 func (c info) isViramaModifier() bool {
-	return c&(viramaModifier|catSmallMask) == viramaModifier
+	return c&(attributesMask|catSmallMask) == viramaModifier
 }
 }

+ 49 - 2
vendor/golang.org/x/net/internal/iana/const.go

@@ -1,5 +1,5 @@
 // go generate gen.go
 // go generate gen.go
-// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
+// Code generated by the command above; DO NOT EDIT.
 
 
 // Package iana provides protocol number resources managed by the Internet Assigned Numbers Authority (IANA).
 // Package iana provides protocol number resources managed by the Internet Assigned Numbers Authority (IANA).
 package iana // import "golang.org/x/net/internal/iana"
 package iana // import "golang.org/x/net/internal/iana"
@@ -38,7 +38,7 @@ const (
 	CongestionExperienced = 0x3 // CE (Congestion Experienced)
 	CongestionExperienced = 0x3 // CE (Congestion Experienced)
 )
 )
 
 
-// Protocol Numbers, Updated: 2016-06-22
+// Protocol Numbers, Updated: 2017-10-13
 const (
 const (
 	ProtocolIP             = 0   // IPv4 encapsulation, pseudo protocol number
 	ProtocolIP             = 0   // IPv4 encapsulation, pseudo protocol number
 	ProtocolHOPOPT         = 0   // IPv6 Hop-by-Hop Option
 	ProtocolHOPOPT         = 0   // IPv6 Hop-by-Hop Option
@@ -178,3 +178,50 @@ const (
 	ProtocolROHC           = 142 // Robust Header Compression
 	ProtocolROHC           = 142 // Robust Header Compression
 	ProtocolReserved       = 255 // Reserved
 	ProtocolReserved       = 255 // Reserved
 )
 )
+
+// Address Family Numbers, Updated: 2016-10-25
+const (
+	AddrFamilyIPv4                          = 1     // IP (IP version 4)
+	AddrFamilyIPv6                          = 2     // IP6 (IP version 6)
+	AddrFamilyNSAP                          = 3     // NSAP
+	AddrFamilyHDLC                          = 4     // HDLC (8-bit multidrop)
+	AddrFamilyBBN1822                       = 5     // BBN 1822
+	AddrFamily802                           = 6     // 802 (includes all 802 media plus Ethernet "canonical format")
+	AddrFamilyE163                          = 7     // E.163
+	AddrFamilyE164                          = 8     // E.164 (SMDS, Frame Relay, ATM)
+	AddrFamilyF69                           = 9     // F.69 (Telex)
+	AddrFamilyX121                          = 10    // X.121 (X.25, Frame Relay)
+	AddrFamilyIPX                           = 11    // IPX
+	AddrFamilyAppletalk                     = 12    // Appletalk
+	AddrFamilyDecnetIV                      = 13    // Decnet IV
+	AddrFamilyBanyanVines                   = 14    // Banyan Vines
+	AddrFamilyE164withSubaddress            = 15    // E.164 with NSAP format subaddress
+	AddrFamilyDNS                           = 16    // DNS (Domain Name System)
+	AddrFamilyDistinguishedName             = 17    // Distinguished Name
+	AddrFamilyASNumber                      = 18    // AS Number
+	AddrFamilyXTPoverIPv4                   = 19    // XTP over IP version 4
+	AddrFamilyXTPoverIPv6                   = 20    // XTP over IP version 6
+	AddrFamilyXTPnativemodeXTP              = 21    // XTP native mode XTP
+	AddrFamilyFibreChannelWorldWidePortName = 22    // Fibre Channel World-Wide Port Name
+	AddrFamilyFibreChannelWorldWideNodeName = 23    // Fibre Channel World-Wide Node Name
+	AddrFamilyGWID                          = 24    // GWID
+	AddrFamilyL2VPN                         = 25    // AFI for L2VPN information
+	AddrFamilyMPLSTPSectionEndpointID       = 26    // MPLS-TP Section Endpoint Identifier
+	AddrFamilyMPLSTPLSPEndpointID           = 27    // MPLS-TP LSP Endpoint Identifier
+	AddrFamilyMPLSTPPseudowireEndpointID    = 28    // MPLS-TP Pseudowire Endpoint Identifier
+	AddrFamilyMTIPv4                        = 29    // MT IP: Multi-Topology IP version 4
+	AddrFamilyMTIPv6                        = 30    // MT IPv6: Multi-Topology IP version 6
+	AddrFamilyEIGRPCommonServiceFamily      = 16384 // EIGRP Common Service Family
+	AddrFamilyEIGRPIPv4ServiceFamily        = 16385 // EIGRP IPv4 Service Family
+	AddrFamilyEIGRPIPv6ServiceFamily        = 16386 // EIGRP IPv6 Service Family
+	AddrFamilyLISPCanonicalAddressFormat    = 16387 // LISP Canonical Address Format (LCAF)
+	AddrFamilyBGPLS                         = 16388 // BGP-LS
+	AddrFamily48bitMAC                      = 16389 // 48-bit MAC
+	AddrFamily64bitMAC                      = 16390 // 64-bit MAC
+	AddrFamilyOUI                           = 16391 // OUI
+	AddrFamilyMACFinal24bits                = 16392 // MAC/24
+	AddrFamilyMACFinal40bits                = 16393 // MAC/40
+	AddrFamilyIPv6Initial64bits             = 16394 // IPv6/64
+	AddrFamilyRBridgePortID                 = 16395 // RBridge Port ID
+	AddrFamilyTRILLNickname                 = 16396 // TRILL Nickname
+)

+ 98 - 4
vendor/golang.org/x/net/internal/iana/gen.go

@@ -28,23 +28,27 @@ var registries = []struct {
 	parse func(io.Writer, io.Reader) error
 	parse func(io.Writer, io.Reader) error
 }{
 }{
 	{
 	{
-		"http://www.iana.org/assignments/dscp-registry/dscp-registry.xml",
+		"https://www.iana.org/assignments/dscp-registry/dscp-registry.xml",
 		parseDSCPRegistry,
 		parseDSCPRegistry,
 	},
 	},
 	{
 	{
-		"http://www.iana.org/assignments/ipv4-tos-byte/ipv4-tos-byte.xml",
+		"https://www.iana.org/assignments/ipv4-tos-byte/ipv4-tos-byte.xml",
 		parseTOSTCByte,
 		parseTOSTCByte,
 	},
 	},
 	{
 	{
-		"http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml",
+		"https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml",
 		parseProtocolNumbers,
 		parseProtocolNumbers,
 	},
 	},
+	{
+		"http://www.iana.org/assignments/address-family-numbers/address-family-numbers.xml",
+		parseAddrFamilyNumbers,
+	},
 }
 }
 
 
 func main() {
 func main() {
 	var bb bytes.Buffer
 	var bb bytes.Buffer
 	fmt.Fprintf(&bb, "// go generate gen.go\n")
 	fmt.Fprintf(&bb, "// go generate gen.go\n")
-	fmt.Fprintf(&bb, "// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n\n")
+	fmt.Fprintf(&bb, "// Code generated by the command above; DO NOT EDIT.\n\n")
 	fmt.Fprintf(&bb, "// Package iana provides protocol number resources managed by the Internet Assigned Numbers Authority (IANA).\n")
 	fmt.Fprintf(&bb, "// Package iana provides protocol number resources managed by the Internet Assigned Numbers Authority (IANA).\n")
 	fmt.Fprintf(&bb, `package iana // import "golang.org/x/net/internal/iana"`+"\n\n")
 	fmt.Fprintf(&bb, `package iana // import "golang.org/x/net/internal/iana"`+"\n\n")
 	for _, r := range registries {
 	for _, r := range registries {
@@ -291,3 +295,93 @@ func (pn *protocolNumbers) escape() []canonProtocolRecord {
 	}
 	}
 	return prs
 	return prs
 }
 }
+
+func parseAddrFamilyNumbers(w io.Writer, r io.Reader) error {
+	dec := xml.NewDecoder(r)
+	var afn addrFamilylNumbers
+	if err := dec.Decode(&afn); err != nil {
+		return err
+	}
+	afrs := afn.escape()
+	fmt.Fprintf(w, "// %s, Updated: %s\n", afn.Title, afn.Updated)
+	fmt.Fprintf(w, "const (\n")
+	for _, afr := range afrs {
+		if afr.Name == "" {
+			continue
+		}
+		fmt.Fprintf(w, "AddrFamily%s = %d", afr.Name, afr.Value)
+		fmt.Fprintf(w, "// %s\n", afr.Descr)
+	}
+	fmt.Fprintf(w, ")\n")
+	return nil
+}
+
+type addrFamilylNumbers struct {
+	XMLName  xml.Name `xml:"registry"`
+	Title    string   `xml:"title"`
+	Updated  string   `xml:"updated"`
+	RegTitle string   `xml:"registry>title"`
+	Note     string   `xml:"registry>note"`
+	Records  []struct {
+		Value string `xml:"value"`
+		Descr string `xml:"description"`
+	} `xml:"registry>record"`
+}
+
+type canonAddrFamilyRecord struct {
+	Name  string
+	Descr string
+	Value int
+}
+
+func (afn *addrFamilylNumbers) escape() []canonAddrFamilyRecord {
+	afrs := make([]canonAddrFamilyRecord, len(afn.Records))
+	sr := strings.NewReplacer(
+		"IP version 4", "IPv4",
+		"IP version 6", "IPv6",
+		"Identifier", "ID",
+		"-", "",
+		"-", "",
+		"/", "",
+		".", "",
+		" ", "",
+	)
+	for i, afr := range afn.Records {
+		if strings.Contains(afr.Descr, "Unassigned") ||
+			strings.Contains(afr.Descr, "Reserved") {
+			continue
+		}
+		afrs[i].Descr = afr.Descr
+		s := strings.TrimSpace(afr.Descr)
+		switch s {
+		case "IP (IP version 4)":
+			afrs[i].Name = "IPv4"
+		case "IP6 (IP version 6)":
+			afrs[i].Name = "IPv6"
+		case "AFI for L2VPN information":
+			afrs[i].Name = "L2VPN"
+		case "E.164 with NSAP format subaddress":
+			afrs[i].Name = "E164withSubaddress"
+		case "MT IP: Multi-Topology IP version 4":
+			afrs[i].Name = "MTIPv4"
+		case "MAC/24":
+			afrs[i].Name = "MACFinal24bits"
+		case "MAC/40":
+			afrs[i].Name = "MACFinal40bits"
+		case "IPv6/64":
+			afrs[i].Name = "IPv6Initial64bits"
+		default:
+			n := strings.Index(s, "(")
+			if n > 0 {
+				s = s[:n]
+			}
+			n = strings.Index(s, ":")
+			if n > 0 {
+				s = s[:n]
+			}
+			afrs[i].Name = sr.Replace(s)
+		}
+		afrs[i].Value, _ = strconv.Atoi(afr.Value)
+	}
+	return afrs
+}

+ 1 - 1
vendor/golang.org/x/net/internal/nettest/helper_stub.go

@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 // license that can be found in the LICENSE file.
 
 
-// +build nacl plan9
+// +build js,wasm nacl plan9
 
 
 package nettest
 package nettest
 
 

+ 7 - 2
vendor/golang.org/x/net/internal/nettest/stack.go

@@ -64,7 +64,7 @@ func TestableNetwork(network string) bool {
 	switch network {
 	switch network {
 	case "unix", "unixgram":
 	case "unix", "unixgram":
 		switch runtime.GOOS {
 		switch runtime.GOOS {
-		case "android", "nacl", "plan9", "windows":
+		case "android", "js", "nacl", "plan9", "windows":
 			return false
 			return false
 		}
 		}
 		if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
 		if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
@@ -72,8 +72,13 @@ func TestableNetwork(network string) bool {
 		}
 		}
 	case "unixpacket":
 	case "unixpacket":
 		switch runtime.GOOS {
 		switch runtime.GOOS {
-		case "android", "darwin", "freebsd", "nacl", "plan9", "windows":
+		case "android", "darwin", "freebsd", "js", "nacl", "plan9", "windows":
 			return false
 			return false
+		case "netbsd":
+			// It passes on amd64 at least. 386 fails (Issue 22927). arm is unknown.
+			if runtime.GOARCH == "386" {
+				return false
+			}
 		}
 		}
 	}
 	}
 	return true
 	return true

+ 5 - 1
vendor/golang.org/x/net/internal/socket/iovec_32bit.go

@@ -10,6 +10,10 @@ package socket
 import "unsafe"
 import "unsafe"
 
 
 func (v *iovec) set(b []byte) {
 func (v *iovec) set(b []byte) {
+	l := len(b)
+	if l == 0 {
+		return
+	}
 	v.Base = (*byte)(unsafe.Pointer(&b[0]))
 	v.Base = (*byte)(unsafe.Pointer(&b[0]))
-	v.Len = uint32(len(b))
+	v.Len = uint32(l)
 }
 }

+ 5 - 1
vendor/golang.org/x/net/internal/socket/iovec_64bit.go

@@ -10,6 +10,10 @@ package socket
 import "unsafe"
 import "unsafe"
 
 
 func (v *iovec) set(b []byte) {
 func (v *iovec) set(b []byte) {
+	l := len(b)
+	if l == 0 {
+		return
+	}
 	v.Base = (*byte)(unsafe.Pointer(&b[0]))
 	v.Base = (*byte)(unsafe.Pointer(&b[0]))
-	v.Len = uint64(len(b))
+	v.Len = uint64(l)
 }
 }

+ 5 - 1
vendor/golang.org/x/net/internal/socket/iovec_solaris_64bit.go

@@ -10,6 +10,10 @@ package socket
 import "unsafe"
 import "unsafe"
 
 
 func (v *iovec) set(b []byte) {
 func (v *iovec) set(b []byte) {
+	l := len(b)
+	if l == 0 {
+		return
+	}
 	v.Base = (*int8)(unsafe.Pointer(&b[0]))
 	v.Base = (*int8)(unsafe.Pointer(&b[0]))
-	v.Len = uint64(len(b))
+	v.Len = uint64(l)
 }
 }

+ 5 - 1
vendor/golang.org/x/net/internal/socket/msghdr_bsdvar.go

@@ -7,6 +7,10 @@
 package socket
 package socket
 
 
 func (h *msghdr) setIov(vs []iovec) {
 func (h *msghdr) setIov(vs []iovec) {
+	l := len(vs)
+	if l == 0 {
+		return
+	}
 	h.Iov = &vs[0]
 	h.Iov = &vs[0]
-	h.Iovlen = int32(len(vs))
+	h.Iovlen = int32(l)
 }
 }

+ 5 - 1
vendor/golang.org/x/net/internal/socket/msghdr_linux_32bit.go

@@ -10,8 +10,12 @@ package socket
 import "unsafe"
 import "unsafe"
 
 
 func (h *msghdr) setIov(vs []iovec) {
 func (h *msghdr) setIov(vs []iovec) {
+	l := len(vs)
+	if l == 0 {
+		return
+	}
 	h.Iov = &vs[0]
 	h.Iov = &vs[0]
-	h.Iovlen = uint32(len(vs))
+	h.Iovlen = uint32(l)
 }
 }
 
 
 func (h *msghdr) setControl(b []byte) {
 func (h *msghdr) setControl(b []byte) {

+ 5 - 1
vendor/golang.org/x/net/internal/socket/msghdr_linux_64bit.go

@@ -10,8 +10,12 @@ package socket
 import "unsafe"
 import "unsafe"
 
 
 func (h *msghdr) setIov(vs []iovec) {
 func (h *msghdr) setIov(vs []iovec) {
+	l := len(vs)
+	if l == 0 {
+		return
+	}
 	h.Iov = &vs[0]
 	h.Iov = &vs[0]
-	h.Iovlen = uint64(len(vs))
+	h.Iovlen = uint64(l)
 }
 }
 
 
 func (h *msghdr) setControl(b []byte) {
 func (h *msghdr) setControl(b []byte) {

+ 5 - 1
vendor/golang.org/x/net/internal/socket/msghdr_openbsd.go

@@ -5,6 +5,10 @@
 package socket
 package socket
 
 
 func (h *msghdr) setIov(vs []iovec) {
 func (h *msghdr) setIov(vs []iovec) {
+	l := len(vs)
+	if l == 0 {
+		return
+	}
 	h.Iov = &vs[0]
 	h.Iov = &vs[0]
-	h.Iovlen = uint32(len(vs))
+	h.Iovlen = uint32(l)
 }
 }

+ 4 - 2
vendor/golang.org/x/net/internal/socket/msghdr_solaris_64bit.go

@@ -13,8 +13,10 @@ func (h *msghdr) pack(vs []iovec, bs [][]byte, oob []byte, sa []byte) {
 	for i := range vs {
 	for i := range vs {
 		vs[i].set(bs[i])
 		vs[i].set(bs[i])
 	}
 	}
-	h.Iov = &vs[0]
-	h.Iovlen = int32(len(vs))
+	if len(vs) > 0 {
+		h.Iov = &vs[0]
+		h.Iovlen = int32(len(vs))
+	}
 	if len(oob) > 0 {
 	if len(oob) > 0 {
 		h.Accrights = (*int8)(unsafe.Pointer(&oob[0]))
 		h.Accrights = (*int8)(unsafe.Pointer(&oob[0]))
 		h.Accrightslen = int32(len(oob))
 		h.Accrightslen = int32(len(oob))

+ 9 - 6
vendor/golang.org/x/net/internal/socket/socket.go

@@ -110,7 +110,7 @@ func ControlMessageSpace(dataLen int) int {
 type ControlMessage []byte
 type ControlMessage []byte
 
 
 // Data returns the data field of the control message at the head on
 // Data returns the data field of the control message at the head on
-// w.
+// m.
 func (m ControlMessage) Data(dataLen int) []byte {
 func (m ControlMessage) Data(dataLen int) []byte {
 	l := controlHeaderLen()
 	l := controlHeaderLen()
 	if len(m) < l || len(m) < l+dataLen {
 	if len(m) < l || len(m) < l+dataLen {
@@ -119,7 +119,7 @@ func (m ControlMessage) Data(dataLen int) []byte {
 	return m[l : l+dataLen]
 	return m[l : l+dataLen]
 }
 }
 
 
-// Next returns the control message at the next on w.
+// Next returns the control message at the next on m.
 //
 //
 // Next works only for standard control messages.
 // Next works only for standard control messages.
 func (m ControlMessage) Next(dataLen int) ControlMessage {
 func (m ControlMessage) Next(dataLen int) ControlMessage {
@@ -131,7 +131,7 @@ func (m ControlMessage) Next(dataLen int) ControlMessage {
 }
 }
 
 
 // MarshalHeader marshals the header fields of the control message at
 // MarshalHeader marshals the header fields of the control message at
-// the head on w.
+// the head on m.
 func (m ControlMessage) MarshalHeader(lvl, typ, dataLen int) error {
 func (m ControlMessage) MarshalHeader(lvl, typ, dataLen int) error {
 	if len(m) < controlHeaderLen() {
 	if len(m) < controlHeaderLen() {
 		return errors.New("short message")
 		return errors.New("short message")
@@ -142,7 +142,7 @@ func (m ControlMessage) MarshalHeader(lvl, typ, dataLen int) error {
 }
 }
 
 
 // ParseHeader parses and returns the header fields of the control
 // ParseHeader parses and returns the header fields of the control
-// message at the head on w.
+// message at the head on m.
 func (m ControlMessage) ParseHeader() (lvl, typ, dataLen int, err error) {
 func (m ControlMessage) ParseHeader() (lvl, typ, dataLen int, err error) {
 	l := controlHeaderLen()
 	l := controlHeaderLen()
 	if len(m) < l {
 	if len(m) < l {
@@ -152,7 +152,7 @@ func (m ControlMessage) ParseHeader() (lvl, typ, dataLen int, err error) {
 	return h.lvl(), h.typ(), int(uint64(h.len()) - uint64(l)), nil
 	return h.lvl(), h.typ(), int(uint64(h.len()) - uint64(l)), nil
 }
 }
 
 
-// Marshal marshals the control message at the head on w, and returns
+// Marshal marshals the control message at the head on m, and returns
 // the next control message.
 // the next control message.
 func (m ControlMessage) Marshal(lvl, typ int, data []byte) (ControlMessage, error) {
 func (m ControlMessage) Marshal(lvl, typ int, data []byte) (ControlMessage, error) {
 	l := len(data)
 	l := len(data)
@@ -167,7 +167,7 @@ func (m ControlMessage) Marshal(lvl, typ int, data []byte) (ControlMessage, erro
 	return m.Next(l), nil
 	return m.Next(l), nil
 }
 }
 
 
-// Parse parses w as a single or multiple control messages.
+// Parse parses m as a single or multiple control messages.
 //
 //
 // Parse works for both standard and compatible messages.
 // Parse works for both standard and compatible messages.
 func (m ControlMessage) Parse() ([]ControlMessage, error) {
 func (m ControlMessage) Parse() ([]ControlMessage, error) {
@@ -175,6 +175,9 @@ func (m ControlMessage) Parse() ([]ControlMessage, error) {
 	for len(m) >= controlHeaderLen() {
 	for len(m) >= controlHeaderLen() {
 		h := (*cmsghdr)(unsafe.Pointer(&m[0]))
 		h := (*cmsghdr)(unsafe.Pointer(&m[0]))
 		l := h.len()
 		l := h.len()
+		if l <= 0 {
+			return nil, errors.New("invalid header length")
+		}
 		if uint64(l) < uint64(controlHeaderLen()) {
 		if uint64(l) < uint64(controlHeaderLen()) {
 			return nil, errors.New("invalid message length")
 			return nil, errors.New("invalid message length")
 		}
 		}

+ 66 - 63
vendor/golang.org/x/net/internal/socket/socket_go1_9_test.go

@@ -119,81 +119,84 @@ func TestUDP(t *testing.T) {
 		t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
 		t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
 	}
 	}
 	defer c.Close()
 	defer c.Close()
+	cc, err := socket.NewConn(c.(net.Conn))
+	if err != nil {
+		t.Fatal(err)
+	}
 
 
 	t.Run("Message", func(t *testing.T) {
 	t.Run("Message", func(t *testing.T) {
-		testUDPMessage(t, c.(net.Conn))
+		data := []byte("HELLO-R-U-THERE")
+		wm := socket.Message{
+			Buffers: bytes.SplitAfter(data, []byte("-")),
+			Addr:    c.LocalAddr(),
+		}
+		if err := cc.SendMsg(&wm, 0); err != nil {
+			t.Fatal(err)
+		}
+		b := make([]byte, 32)
+		rm := socket.Message{
+			Buffers: [][]byte{b[:1], b[1:3], b[3:7], b[7:11], b[11:]},
+		}
+		if err := cc.RecvMsg(&rm, 0); err != nil {
+			t.Fatal(err)
+		}
+		if !bytes.Equal(b[:rm.N], data) {
+			t.Fatalf("got %#v; want %#v", b[:rm.N], data)
+		}
 	})
 	})
 	switch runtime.GOOS {
 	switch runtime.GOOS {
-	case "linux":
+	case "android", "linux":
 		t.Run("Messages", func(t *testing.T) {
 		t.Run("Messages", func(t *testing.T) {
-			testUDPMessages(t, c.(net.Conn))
+			data := []byte("HELLO-R-U-THERE")
+			wmbs := bytes.SplitAfter(data, []byte("-"))
+			wms := []socket.Message{
+				{Buffers: wmbs[:1], Addr: c.LocalAddr()},
+				{Buffers: wmbs[1:], Addr: c.LocalAddr()},
+			}
+			n, err := cc.SendMsgs(wms, 0)
+			if err != nil {
+				t.Fatal(err)
+			}
+			if n != len(wms) {
+				t.Fatalf("got %d; want %d", n, len(wms))
+			}
+			b := make([]byte, 32)
+			rmbs := [][][]byte{{b[:len(wmbs[0])]}, {b[len(wmbs[0]):]}}
+			rms := []socket.Message{
+				{Buffers: rmbs[0]},
+				{Buffers: rmbs[1]},
+			}
+			n, err = cc.RecvMsgs(rms, 0)
+			if err != nil {
+				t.Fatal(err)
+			}
+			if n != len(rms) {
+				t.Fatalf("got %d; want %d", n, len(rms))
+			}
+			nn := 0
+			for i := 0; i < n; i++ {
+				nn += rms[i].N
+			}
+			if !bytes.Equal(b[:nn], data) {
+				t.Fatalf("got %#v; want %#v", b[:nn], data)
+			}
 		})
 		})
 	}
 	}
-}
 
 
-func testUDPMessage(t *testing.T, c net.Conn) {
-	cc, err := socket.NewConn(c)
-	if err != nil {
-		t.Fatal(err)
-	}
-	data := []byte("HELLO-R-U-THERE")
+	// The behavior of transmission for zero byte paylaod depends
+	// on each platform implementation. Some may transmit only
+	// protocol header and options, other may transmit nothing.
+	// We test only that SendMsg and SendMsgs will not crash with
+	// empty buffers.
 	wm := socket.Message{
 	wm := socket.Message{
-		Buffers: bytes.SplitAfter(data, []byte("-")),
+		Buffers: [][]byte{{}},
 		Addr:    c.LocalAddr(),
 		Addr:    c.LocalAddr(),
 	}
 	}
-	if err := cc.SendMsg(&wm, 0); err != nil {
-		t.Fatal(err)
-	}
-	b := make([]byte, 32)
-	rm := socket.Message{
-		Buffers: [][]byte{b[:1], b[1:3], b[3:7], b[7:11], b[11:]},
-	}
-	if err := cc.RecvMsg(&rm, 0); err != nil {
-		t.Fatal(err)
-	}
-	if !bytes.Equal(b[:rm.N], data) {
-		t.Fatalf("got %#v; want %#v", b[:rm.N], data)
-	}
-}
-
-func testUDPMessages(t *testing.T, c net.Conn) {
-	cc, err := socket.NewConn(c)
-	if err != nil {
-		t.Fatal(err)
-	}
-	data := []byte("HELLO-R-U-THERE")
-	wmbs := bytes.SplitAfter(data, []byte("-"))
+	cc.SendMsg(&wm, 0)
 	wms := []socket.Message{
 	wms := []socket.Message{
-		{Buffers: wmbs[:1], Addr: c.LocalAddr()},
-		{Buffers: wmbs[1:], Addr: c.LocalAddr()},
-	}
-	n, err := cc.SendMsgs(wms, 0)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if n != len(wms) {
-		t.Fatalf("got %d; want %d", n, len(wms))
-	}
-	b := make([]byte, 32)
-	rmbs := [][][]byte{{b[:len(wmbs[0])]}, {b[len(wmbs[0]):]}}
-	rms := []socket.Message{
-		{Buffers: rmbs[0]},
-		{Buffers: rmbs[1]},
-	}
-	n, err = cc.RecvMsgs(rms, 0)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if n != len(rms) {
-		t.Fatalf("got %d; want %d", n, len(rms))
-	}
-	nn := 0
-	for i := 0; i < n; i++ {
-		nn += rms[i].N
-	}
-	if !bytes.Equal(b[:nn], data) {
-		t.Fatalf("got %#v; want %#v", b[:nn], data)
+		{Buffers: [][]byte{{}}, Addr: c.LocalAddr()},
 	}
 	}
+	cc.SendMsgs(wms, 0)
 }
 }
 
 
 func BenchmarkUDP(b *testing.B) {
 func BenchmarkUDP(b *testing.B) {
@@ -230,7 +233,7 @@ func BenchmarkUDP(b *testing.B) {
 			}
 			}
 		})
 		})
 		switch runtime.GOOS {
 		switch runtime.GOOS {
-		case "linux":
+		case "android", "linux":
 			wms := make([]socket.Message, M)
 			wms := make([]socket.Message, M)
 			for i := range wms {
 			for i := range wms {
 				wms[i].Buffers = [][]byte{data}
 				wms[i].Buffers = [][]byte{data}

+ 3 - 3
vendor/golang.org/x/net/internal/socket/sys_posix.go

@@ -34,7 +34,7 @@ func marshalSockaddr(ip net.IP, port int, zone string) []byte {
 	if ip4 := ip.To4(); ip4 != nil {
 	if ip4 := ip.To4(); ip4 != nil {
 		b := make([]byte, sizeofSockaddrInet)
 		b := make([]byte, sizeofSockaddrInet)
 		switch runtime.GOOS {
 		switch runtime.GOOS {
-		case "linux", "solaris", "windows":
+		case "android", "linux", "solaris", "windows":
 			NativeEndian.PutUint16(b[:2], uint16(sysAF_INET))
 			NativeEndian.PutUint16(b[:2], uint16(sysAF_INET))
 		default:
 		default:
 			b[0] = sizeofSockaddrInet
 			b[0] = sizeofSockaddrInet
@@ -47,7 +47,7 @@ func marshalSockaddr(ip net.IP, port int, zone string) []byte {
 	if ip6 := ip.To16(); ip6 != nil && ip.To4() == nil {
 	if ip6 := ip.To16(); ip6 != nil && ip.To4() == nil {
 		b := make([]byte, sizeofSockaddrInet6)
 		b := make([]byte, sizeofSockaddrInet6)
 		switch runtime.GOOS {
 		switch runtime.GOOS {
-		case "linux", "solaris", "windows":
+		case "android", "linux", "solaris", "windows":
 			NativeEndian.PutUint16(b[:2], uint16(sysAF_INET6))
 			NativeEndian.PutUint16(b[:2], uint16(sysAF_INET6))
 		default:
 		default:
 			b[0] = sizeofSockaddrInet6
 			b[0] = sizeofSockaddrInet6
@@ -69,7 +69,7 @@ func parseInetAddr(b []byte, network string) (net.Addr, error) {
 	}
 	}
 	var af int
 	var af int
 	switch runtime.GOOS {
 	switch runtime.GOOS {
-	case "linux", "solaris", "windows":
+	case "android", "linux", "solaris", "windows":
 		af = int(NativeEndian.Uint16(b[:2]))
 		af = int(NativeEndian.Uint16(b[:2]))
 	default:
 	default:
 		af = int(b[1])
 		af = int(b[1])

+ 61 - 0
vendor/golang.org/x/net/internal/socket/zsys_darwin_arm64.go

@@ -0,0 +1,61 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_darwin.go
+
+package socket
+
+const (
+	sysAF_UNSPEC = 0x0
+	sysAF_INET   = 0x2
+	sysAF_INET6  = 0x1e
+
+	sysSOCK_RAW = 0x3
+)
+
+type iovec struct {
+	Base *byte
+	Len  uint64
+}
+
+type msghdr struct {
+	Name       *byte
+	Namelen    uint32
+	Pad_cgo_0  [4]byte
+	Iov        *iovec
+	Iovlen     int32
+	Pad_cgo_1  [4]byte
+	Control    *byte
+	Controllen uint32
+	Flags      int32
+}
+
+type cmsghdr struct {
+	Len   uint32
+	Level int32
+	Type  int32
+}
+
+type sockaddrInet struct {
+	Len    uint8
+	Family uint8
+	Port   uint16
+	Addr   [4]byte /* in_addr */
+	Zero   [8]int8
+}
+
+type sockaddrInet6 struct {
+	Len      uint8
+	Family   uint8
+	Port     uint16
+	Flowinfo uint32
+	Addr     [16]byte /* in6_addr */
+	Scope_id uint32
+}
+
+const (
+	sizeofIovec   = 0x10
+	sizeofMsghdr  = 0x30
+	sizeofCmsghdr = 0xc
+
+	sizeofSockaddrInet  = 0x10
+	sizeofSockaddrInet6 = 0x1c
+)

+ 6 - 0
vendor/golang.org/x/net/internal/socket/zsys_netbsd_arm.go

@@ -26,6 +26,11 @@ type msghdr struct {
 	Flags      int32
 	Flags      int32
 }
 }
 
 
+type mmsghdr struct {
+	Hdr msghdr
+	Len uint32
+}
+
 type cmsghdr struct {
 type cmsghdr struct {
 	Len   uint32
 	Len   uint32
 	Level int32
 	Level int32
@@ -52,6 +57,7 @@ type sockaddrInet6 struct {
 const (
 const (
 	sizeofIovec   = 0x8
 	sizeofIovec   = 0x8
 	sizeofMsghdr  = 0x1c
 	sizeofMsghdr  = 0x1c
+	sizeofMmsghdr = 0x20
 	sizeofCmsghdr = 0xc
 	sizeofCmsghdr = 0xc
 
 
 	sizeofSockaddrInet  = 0x10
 	sizeofSockaddrInet  = 0x10

+ 168 - 0
vendor/golang.org/x/net/internal/socks/client.go

@@ -0,0 +1,168 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package socks
+
+import (
+	"context"
+	"errors"
+	"io"
+	"net"
+	"strconv"
+	"time"
+)
+
+var (
+	noDeadline   = time.Time{}
+	aLongTimeAgo = time.Unix(1, 0)
+)
+
+func (d *Dialer) connect(ctx context.Context, c net.Conn, address string) (_ net.Addr, ctxErr error) {
+	host, port, err := splitHostPort(address)
+	if err != nil {
+		return nil, err
+	}
+	if deadline, ok := ctx.Deadline(); ok && !deadline.IsZero() {
+		c.SetDeadline(deadline)
+		defer c.SetDeadline(noDeadline)
+	}
+	if ctx != context.Background() {
+		errCh := make(chan error, 1)
+		done := make(chan struct{})
+		defer func() {
+			close(done)
+			if ctxErr == nil {
+				ctxErr = <-errCh
+			}
+		}()
+		go func() {
+			select {
+			case <-ctx.Done():
+				c.SetDeadline(aLongTimeAgo)
+				errCh <- ctx.Err()
+			case <-done:
+				errCh <- nil
+			}
+		}()
+	}
+
+	b := make([]byte, 0, 6+len(host)) // the size here is just an estimate
+	b = append(b, Version5)
+	if len(d.AuthMethods) == 0 || d.Authenticate == nil {
+		b = append(b, 1, byte(AuthMethodNotRequired))
+	} else {
+		ams := d.AuthMethods
+		if len(ams) > 255 {
+			return nil, errors.New("too many authentication methods")
+		}
+		b = append(b, byte(len(ams)))
+		for _, am := range ams {
+			b = append(b, byte(am))
+		}
+	}
+	if _, ctxErr = c.Write(b); ctxErr != nil {
+		return
+	}
+
+	if _, ctxErr = io.ReadFull(c, b[:2]); ctxErr != nil {
+		return
+	}
+	if b[0] != Version5 {
+		return nil, errors.New("unexpected protocol version " + strconv.Itoa(int(b[0])))
+	}
+	am := AuthMethod(b[1])
+	if am == AuthMethodNoAcceptableMethods {
+		return nil, errors.New("no acceptable authentication methods")
+	}
+	if d.Authenticate != nil {
+		if ctxErr = d.Authenticate(ctx, c, am); ctxErr != nil {
+			return
+		}
+	}
+
+	b = b[:0]
+	b = append(b, Version5, byte(d.cmd), 0)
+	if ip := net.ParseIP(host); ip != nil {
+		if ip4 := ip.To4(); ip4 != nil {
+			b = append(b, AddrTypeIPv4)
+			b = append(b, ip4...)
+		} else if ip6 := ip.To16(); ip6 != nil {
+			b = append(b, AddrTypeIPv6)
+			b = append(b, ip6...)
+		} else {
+			return nil, errors.New("unknown address type")
+		}
+	} else {
+		if len(host) > 255 {
+			return nil, errors.New("FQDN too long")
+		}
+		b = append(b, AddrTypeFQDN)
+		b = append(b, byte(len(host)))
+		b = append(b, host...)
+	}
+	b = append(b, byte(port>>8), byte(port))
+	if _, ctxErr = c.Write(b); ctxErr != nil {
+		return
+	}
+
+	if _, ctxErr = io.ReadFull(c, b[:4]); ctxErr != nil {
+		return
+	}
+	if b[0] != Version5 {
+		return nil, errors.New("unexpected protocol version " + strconv.Itoa(int(b[0])))
+	}
+	if cmdErr := Reply(b[1]); cmdErr != StatusSucceeded {
+		return nil, errors.New("unknown error " + cmdErr.String())
+	}
+	if b[2] != 0 {
+		return nil, errors.New("non-zero reserved field")
+	}
+	l := 2
+	var a Addr
+	switch b[3] {
+	case AddrTypeIPv4:
+		l += net.IPv4len
+		a.IP = make(net.IP, net.IPv4len)
+	case AddrTypeIPv6:
+		l += net.IPv6len
+		a.IP = make(net.IP, net.IPv6len)
+	case AddrTypeFQDN:
+		if _, err := io.ReadFull(c, b[:1]); err != nil {
+			return nil, err
+		}
+		l += int(b[0])
+	default:
+		return nil, errors.New("unknown address type " + strconv.Itoa(int(b[3])))
+	}
+	if cap(b) < l {
+		b = make([]byte, l)
+	} else {
+		b = b[:l]
+	}
+	if _, ctxErr = io.ReadFull(c, b); ctxErr != nil {
+		return
+	}
+	if a.IP != nil {
+		copy(a.IP, b)
+	} else {
+		a.Name = string(b[:len(b)-2])
+	}
+	a.Port = int(b[len(b)-2])<<8 | int(b[len(b)-1])
+	return &a, nil
+}
+
+func splitHostPort(address string) (string, int, error) {
+	host, port, err := net.SplitHostPort(address)
+	if err != nil {
+		return "", 0, err
+	}
+	portnum, err := strconv.Atoi(port)
+	if err != nil {
+		return "", 0, err
+	}
+	if 1 > portnum || portnum > 0xffff {
+		return "", 0, errors.New("port number out of range " + port)
+	}
+	return host, portnum, nil
+}

+ 158 - 0
vendor/golang.org/x/net/internal/socks/dial_test.go

@@ -0,0 +1,158 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package socks_test
+
+import (
+	"context"
+	"io"
+	"math/rand"
+	"net"
+	"os"
+	"testing"
+	"time"
+
+	"golang.org/x/net/internal/socks"
+	"golang.org/x/net/internal/sockstest"
+)
+
+const (
+	targetNetwork  = "tcp6"
+	targetHostname = "fqdn.doesnotexist"
+	targetHostIP   = "2001:db8::1"
+	targetPort     = "5963"
+)
+
+func TestDial(t *testing.T) {
+	t.Run("Connect", func(t *testing.T) {
+		ss, err := sockstest.NewServer(sockstest.NoAuthRequired, sockstest.NoProxyRequired)
+		if err != nil {
+			t.Error(err)
+			return
+		}
+		defer ss.Close()
+		d := socks.NewDialer(ss.Addr().Network(), ss.Addr().String())
+		d.AuthMethods = []socks.AuthMethod{
+			socks.AuthMethodNotRequired,
+			socks.AuthMethodUsernamePassword,
+		}
+		d.Authenticate = (&socks.UsernamePassword{
+			Username: "username",
+			Password: "password",
+		}).Authenticate
+		c, err := d.Dial(targetNetwork, net.JoinHostPort(targetHostIP, targetPort))
+		if err == nil {
+			c.(*socks.Conn).BoundAddr()
+			c.Close()
+		}
+		if err != nil {
+			t.Error(err)
+			return
+		}
+	})
+	t.Run("Cancel", func(t *testing.T) {
+		ss, err := sockstest.NewServer(sockstest.NoAuthRequired, blackholeCmdFunc)
+		if err != nil {
+			t.Error(err)
+			return
+		}
+		defer ss.Close()
+		d := socks.NewDialer(ss.Addr().Network(), ss.Addr().String())
+		ctx, cancel := context.WithCancel(context.Background())
+		defer cancel()
+		dialErr := make(chan error)
+		go func() {
+			c, err := d.DialContext(ctx, ss.TargetAddr().Network(), net.JoinHostPort(targetHostname, targetPort))
+			if err == nil {
+				c.Close()
+			}
+			dialErr <- err
+		}()
+		time.Sleep(100 * time.Millisecond)
+		cancel()
+		err = <-dialErr
+		if perr, nerr := parseDialError(err); perr != context.Canceled && nerr == nil {
+			t.Errorf("got %v; want context.Canceled or equivalent", err)
+			return
+		}
+	})
+	t.Run("Deadline", func(t *testing.T) {
+		ss, err := sockstest.NewServer(sockstest.NoAuthRequired, blackholeCmdFunc)
+		if err != nil {
+			t.Error(err)
+			return
+		}
+		defer ss.Close()
+		d := socks.NewDialer(ss.Addr().Network(), ss.Addr().String())
+		ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(100*time.Millisecond))
+		defer cancel()
+		c, err := d.DialContext(ctx, ss.TargetAddr().Network(), net.JoinHostPort(targetHostname, targetPort))
+		if err == nil {
+			c.Close()
+		}
+		if perr, nerr := parseDialError(err); perr != context.DeadlineExceeded && nerr == nil {
+			t.Errorf("got %v; want context.DeadlineExceeded or equivalent", err)
+			return
+		}
+	})
+	t.Run("WithRogueServer", func(t *testing.T) {
+		ss, err := sockstest.NewServer(sockstest.NoAuthRequired, rogueCmdFunc)
+		if err != nil {
+			t.Error(err)
+			return
+		}
+		defer ss.Close()
+		d := socks.NewDialer(ss.Addr().Network(), ss.Addr().String())
+		for i := 0; i < 2*len(rogueCmdList); i++ {
+			ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(100*time.Millisecond))
+			defer cancel()
+			c, err := d.DialContext(ctx, targetNetwork, net.JoinHostPort(targetHostIP, targetPort))
+			if err == nil {
+				t.Log(c.(*socks.Conn).BoundAddr())
+				c.Close()
+				t.Error("should fail")
+			}
+		}
+	})
+}
+
+func blackholeCmdFunc(rw io.ReadWriter, b []byte) error {
+	if _, err := sockstest.ParseCmdRequest(b); err != nil {
+		return err
+	}
+	var bb [1]byte
+	for {
+		if _, err := rw.Read(bb[:]); err != nil {
+			return err
+		}
+	}
+}
+
+func rogueCmdFunc(rw io.ReadWriter, b []byte) error {
+	if _, err := sockstest.ParseCmdRequest(b); err != nil {
+		return err
+	}
+	rw.Write(rogueCmdList[rand.Intn(len(rogueCmdList))])
+	return nil
+}
+
+var rogueCmdList = [][]byte{
+	{0x05},
+	{0x06, 0x00, 0x00, 0x01, 192, 0, 2, 1, 0x17, 0x4b},
+	{0x05, 0x00, 0xff, 0x01, 192, 0, 2, 2, 0x17, 0x4b},
+	{0x05, 0x00, 0x00, 0x01, 192, 0, 2, 3},
+	{0x05, 0x00, 0x00, 0x03, 0x04, 'F', 'Q', 'D', 'N'},
+}
+
+func parseDialError(err error) (perr, nerr error) {
+	if e, ok := err.(*net.OpError); ok {
+		err = e.Err
+		nerr = e
+	}
+	if e, ok := err.(*os.SyscallError); ok {
+		err = e.Err
+	}
+	perr = err
+	return
+}

+ 265 - 0
vendor/golang.org/x/net/internal/socks/socks.go

@@ -0,0 +1,265 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package socks provides a SOCKS version 5 client implementation.
+//
+// SOCKS protocol version 5 is defined in RFC 1928.
+// Username/Password authentication for SOCKS version 5 is defined in
+// RFC 1929.
+package socks
+
+import (
+	"context"
+	"errors"
+	"io"
+	"net"
+	"strconv"
+)
+
+// A Command represents a SOCKS command.
+type Command int
+
+func (cmd Command) String() string {
+	switch cmd {
+	case CmdConnect:
+		return "socks connect"
+	case cmdBind:
+		return "socks bind"
+	default:
+		return "socks " + strconv.Itoa(int(cmd))
+	}
+}
+
+// An AuthMethod represents a SOCKS authentication method.
+type AuthMethod int
+
+// A Reply represents a SOCKS command reply code.
+type Reply int
+
+func (code Reply) String() string {
+	switch code {
+	case StatusSucceeded:
+		return "succeeded"
+	case 0x01:
+		return "general SOCKS server failure"
+	case 0x02:
+		return "connection not allowed by ruleset"
+	case 0x03:
+		return "network unreachable"
+	case 0x04:
+		return "host unreachable"
+	case 0x05:
+		return "connection refused"
+	case 0x06:
+		return "TTL expired"
+	case 0x07:
+		return "command not supported"
+	case 0x08:
+		return "address type not supported"
+	default:
+		return "unknown code: " + strconv.Itoa(int(code))
+	}
+}
+
+// Wire protocol constants.
+const (
+	Version5 = 0x05
+
+	AddrTypeIPv4 = 0x01
+	AddrTypeFQDN = 0x03
+	AddrTypeIPv6 = 0x04
+
+	CmdConnect Command = 0x01 // establishes an active-open forward proxy connection
+	cmdBind    Command = 0x02 // establishes a passive-open forward proxy connection
+
+	AuthMethodNotRequired         AuthMethod = 0x00 // no authentication required
+	AuthMethodUsernamePassword    AuthMethod = 0x02 // use username/password
+	AuthMethodNoAcceptableMethods AuthMethod = 0xff // no acceptable authetication methods
+
+	StatusSucceeded Reply = 0x00
+)
+
+// An Addr represents a SOCKS-specific address.
+// Either Name or IP is used exclusively.
+type Addr struct {
+	Name string // fully-qualified domain name
+	IP   net.IP
+	Port int
+}
+
+func (a *Addr) Network() string { return "socks" }
+
+func (a *Addr) String() string {
+	if a == nil {
+		return "<nil>"
+	}
+	port := strconv.Itoa(a.Port)
+	if a.IP == nil {
+		return net.JoinHostPort(a.Name, port)
+	}
+	return net.JoinHostPort(a.IP.String(), port)
+}
+
+// A Conn represents a forward proxy connection.
+type Conn struct {
+	net.Conn
+
+	boundAddr net.Addr
+}
+
+// BoundAddr returns the address assigned by the proxy server for
+// connecting to the command target address from the proxy server.
+func (c *Conn) BoundAddr() net.Addr {
+	if c == nil {
+		return nil
+	}
+	return c.boundAddr
+}
+
+// A Dialer holds SOCKS-specific options.
+type Dialer struct {
+	cmd          Command // either CmdConnect or cmdBind
+	proxyNetwork string  // network between a proxy server and a client
+	proxyAddress string  // proxy server address
+
+	// ProxyDial specifies the optional dial function for
+	// establishing the transport connection.
+	ProxyDial func(context.Context, string, string) (net.Conn, error)
+
+	// AuthMethods specifies the list of request authention
+	// methods.
+	// If empty, SOCKS client requests only AuthMethodNotRequired.
+	AuthMethods []AuthMethod
+
+	// Authenticate specifies the optional authentication
+	// function. It must be non-nil when AuthMethods is not empty.
+	// It must return an error when the authentication is failed.
+	Authenticate func(context.Context, io.ReadWriter, AuthMethod) error
+}
+
+// DialContext connects to the provided address on the provided
+// network.
+//
+// The returned error value may be a net.OpError. When the Op field of
+// net.OpError contains "socks", the Source field contains a proxy
+// server address and the Addr field contains a command target
+// address.
+//
+// See func Dial of the net package of standard library for a
+// description of the network and address parameters.
+func (d *Dialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
+	switch network {
+	case "tcp", "tcp6", "tcp4":
+	default:
+		proxy, dst, _ := d.pathAddrs(address)
+		return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: errors.New("network not implemented")}
+	}
+	switch d.cmd {
+	case CmdConnect, cmdBind:
+	default:
+		proxy, dst, _ := d.pathAddrs(address)
+		return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: errors.New("command not implemented")}
+	}
+	if ctx == nil {
+		ctx = context.Background()
+	}
+	var err error
+	var c net.Conn
+	if d.ProxyDial != nil {
+		c, err = d.ProxyDial(ctx, d.proxyNetwork, d.proxyAddress)
+	} else {
+		var dd net.Dialer
+		c, err = dd.DialContext(ctx, d.proxyNetwork, d.proxyAddress)
+	}
+	if err != nil {
+		proxy, dst, _ := d.pathAddrs(address)
+		return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err}
+	}
+	a, err := d.connect(ctx, c, address)
+	if err != nil {
+		c.Close()
+		proxy, dst, _ := d.pathAddrs(address)
+		return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err}
+	}
+	return &Conn{Conn: c, boundAddr: a}, nil
+}
+
+// Dial connects to the provided address on the provided network.
+//
+// Deprecated: Use DialContext instead.
+func (d *Dialer) Dial(network, address string) (net.Conn, error) {
+	return d.DialContext(context.Background(), network, address)
+}
+
+func (d *Dialer) pathAddrs(address string) (proxy, dst net.Addr, err error) {
+	for i, s := range []string{d.proxyAddress, address} {
+		host, port, err := splitHostPort(s)
+		if err != nil {
+			return nil, nil, err
+		}
+		a := &Addr{Port: port}
+		a.IP = net.ParseIP(host)
+		if a.IP == nil {
+			a.Name = host
+		}
+		if i == 0 {
+			proxy = a
+		} else {
+			dst = a
+		}
+	}
+	return
+}
+
+// NewDialer returns a new Dialer that dials through the provided
+// proxy server's network and address.
+func NewDialer(network, address string) *Dialer {
+	return &Dialer{proxyNetwork: network, proxyAddress: address, cmd: CmdConnect}
+}
+
+const (
+	authUsernamePasswordVersion = 0x01
+	authStatusSucceeded         = 0x00
+)
+
+// UsernamePassword are the credentials for the username/password
+// authentication method.
+type UsernamePassword struct {
+	Username string
+	Password string
+}
+
+// Authenticate authenticates a pair of username and password with the
+// proxy server.
+func (up *UsernamePassword) Authenticate(ctx context.Context, rw io.ReadWriter, auth AuthMethod) error {
+	switch auth {
+	case AuthMethodNotRequired:
+		return nil
+	case AuthMethodUsernamePassword:
+		if len(up.Username) == 0 || len(up.Username) > 255 || len(up.Password) == 0 || len(up.Password) > 255 {
+			return errors.New("invalid username/password")
+		}
+		b := []byte{authUsernamePasswordVersion}
+		b = append(b, byte(len(up.Username)))
+		b = append(b, up.Username...)
+		b = append(b, byte(len(up.Password)))
+		b = append(b, up.Password...)
+		// TODO(mikio): handle IO deadlines and cancelation if
+		// necessary
+		if _, err := rw.Write(b); err != nil {
+			return err
+		}
+		if _, err := io.ReadFull(rw, b[:2]); err != nil {
+			return err
+		}
+		if b[0] != authUsernamePasswordVersion {
+			return errors.New("invalid username/password version")
+		}
+		if b[1] != authStatusSucceeded {
+			return errors.New("username/password authentication failed")
+		}
+		return nil
+	}
+	return errors.New("unsupported authentication method " + strconv.Itoa(int(auth)))
+}

+ 241 - 0
vendor/golang.org/x/net/internal/sockstest/server.go

@@ -0,0 +1,241 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package sockstest provides utilities for SOCKS testing.
+package sockstest
+
+import (
+	"errors"
+	"io"
+	"net"
+
+	"golang.org/x/net/internal/nettest"
+	"golang.org/x/net/internal/socks"
+)
+
+// An AuthRequest represents an authentication request.
+type AuthRequest struct {
+	Version int
+	Methods []socks.AuthMethod
+}
+
+// ParseAuthRequest parses an authentication request.
+func ParseAuthRequest(b []byte) (*AuthRequest, error) {
+	if len(b) < 2 {
+		return nil, errors.New("short auth request")
+	}
+	if b[0] != socks.Version5 {
+		return nil, errors.New("unexpected protocol version")
+	}
+	if len(b)-2 < int(b[1]) {
+		return nil, errors.New("short auth request")
+	}
+	req := &AuthRequest{Version: int(b[0])}
+	if b[1] > 0 {
+		req.Methods = make([]socks.AuthMethod, b[1])
+		for i, m := range b[2 : 2+b[1]] {
+			req.Methods[i] = socks.AuthMethod(m)
+		}
+	}
+	return req, nil
+}
+
+// MarshalAuthReply returns an authentication reply in wire format.
+func MarshalAuthReply(ver int, m socks.AuthMethod) ([]byte, error) {
+	return []byte{byte(ver), byte(m)}, nil
+}
+
+// A CmdRequest repesents a command request.
+type CmdRequest struct {
+	Version int
+	Cmd     socks.Command
+	Addr    socks.Addr
+}
+
+// ParseCmdRequest parses a command request.
+func ParseCmdRequest(b []byte) (*CmdRequest, error) {
+	if len(b) < 7 {
+		return nil, errors.New("short cmd request")
+	}
+	if b[0] != socks.Version5 {
+		return nil, errors.New("unexpected protocol version")
+	}
+	if socks.Command(b[1]) != socks.CmdConnect {
+		return nil, errors.New("unexpected command")
+	}
+	if b[2] != 0 {
+		return nil, errors.New("non-zero reserved field")
+	}
+	req := &CmdRequest{Version: int(b[0]), Cmd: socks.Command(b[1])}
+	l := 2
+	off := 4
+	switch b[3] {
+	case socks.AddrTypeIPv4:
+		l += net.IPv4len
+		req.Addr.IP = make(net.IP, net.IPv4len)
+	case socks.AddrTypeIPv6:
+		l += net.IPv6len
+		req.Addr.IP = make(net.IP, net.IPv6len)
+	case socks.AddrTypeFQDN:
+		l += int(b[4])
+		off = 5
+	default:
+		return nil, errors.New("unknown address type")
+	}
+	if len(b[off:]) < l {
+		return nil, errors.New("short cmd request")
+	}
+	if req.Addr.IP != nil {
+		copy(req.Addr.IP, b[off:])
+	} else {
+		req.Addr.Name = string(b[off : off+l-2])
+	}
+	req.Addr.Port = int(b[off+l-2])<<8 | int(b[off+l-1])
+	return req, nil
+}
+
+// MarshalCmdReply returns a command reply in wire format.
+func MarshalCmdReply(ver int, reply socks.Reply, a *socks.Addr) ([]byte, error) {
+	b := make([]byte, 4)
+	b[0] = byte(ver)
+	b[1] = byte(reply)
+	if a.Name != "" {
+		if len(a.Name) > 255 {
+			return nil, errors.New("fqdn too long")
+		}
+		b[3] = socks.AddrTypeFQDN
+		b = append(b, byte(len(a.Name)))
+		b = append(b, a.Name...)
+	} else if ip4 := a.IP.To4(); ip4 != nil {
+		b[3] = socks.AddrTypeIPv4
+		b = append(b, ip4...)
+	} else if ip6 := a.IP.To16(); ip6 != nil {
+		b[3] = socks.AddrTypeIPv6
+		b = append(b, ip6...)
+	} else {
+		return nil, errors.New("unknown address type")
+	}
+	b = append(b, byte(a.Port>>8), byte(a.Port))
+	return b, nil
+}
+
+// A Server repesents a server for handshake testing.
+type Server struct {
+	ln net.Listener
+}
+
+// Addr rerurns a server address.
+func (s *Server) Addr() net.Addr {
+	return s.ln.Addr()
+}
+
+// TargetAddr returns a fake final destination address.
+//
+// The returned address is only valid for testing with Server.
+func (s *Server) TargetAddr() net.Addr {
+	a := s.ln.Addr()
+	switch a := a.(type) {
+	case *net.TCPAddr:
+		if a.IP.To4() != nil {
+			return &net.TCPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 5963}
+		}
+		if a.IP.To16() != nil && a.IP.To4() == nil {
+			return &net.TCPAddr{IP: net.IPv6loopback, Port: 5963}
+		}
+	}
+	return nil
+}
+
+// Close closes the server.
+func (s *Server) Close() error {
+	return s.ln.Close()
+}
+
+func (s *Server) serve(authFunc, cmdFunc func(io.ReadWriter, []byte) error) {
+	c, err := s.ln.Accept()
+	if err != nil {
+		return
+	}
+	defer c.Close()
+	go s.serve(authFunc, cmdFunc)
+	b := make([]byte, 512)
+	n, err := c.Read(b)
+	if err != nil {
+		return
+	}
+	if err := authFunc(c, b[:n]); err != nil {
+		return
+	}
+	n, err = c.Read(b)
+	if err != nil {
+		return
+	}
+	if err := cmdFunc(c, b[:n]); err != nil {
+		return
+	}
+}
+
+// NewServer returns a new server.
+//
+// The provided authFunc and cmdFunc must parse requests and return
+// appropriate replies to clients.
+func NewServer(authFunc, cmdFunc func(io.ReadWriter, []byte) error) (*Server, error) {
+	var err error
+	s := new(Server)
+	s.ln, err = nettest.NewLocalListener("tcp")
+	if err != nil {
+		return nil, err
+	}
+	go s.serve(authFunc, cmdFunc)
+	return s, nil
+}
+
+// NoAuthRequired handles a no-authentication-required signaling.
+func NoAuthRequired(rw io.ReadWriter, b []byte) error {
+	req, err := ParseAuthRequest(b)
+	if err != nil {
+		return err
+	}
+	b, err = MarshalAuthReply(req.Version, socks.AuthMethodNotRequired)
+	if err != nil {
+		return err
+	}
+	n, err := rw.Write(b)
+	if err != nil {
+		return err
+	}
+	if n != len(b) {
+		return errors.New("short write")
+	}
+	return nil
+}
+
+// NoProxyRequired handles a command signaling without constructing a
+// proxy connection to the final destination.
+func NoProxyRequired(rw io.ReadWriter, b []byte) error {
+	req, err := ParseCmdRequest(b)
+	if err != nil {
+		return err
+	}
+	req.Addr.Port += 1
+	if req.Addr.Name != "" {
+		req.Addr.Name = "boundaddr.doesnotexist"
+	} else if req.Addr.IP.To4() != nil {
+		req.Addr.IP = net.IPv4(127, 0, 0, 1)
+	} else {
+		req.Addr.IP = net.IPv6loopback
+	}
+	b, err = MarshalCmdReply(socks.Version5, socks.StatusSucceeded, &req.Addr)
+	if err != nil {
+		return err
+	}
+	n, err := rw.Write(b)
+	if err != nil {
+		return err
+	}
+	if n != len(b) {
+		return errors.New("short write")
+	}
+	return nil
+}

+ 103 - 0
vendor/golang.org/x/net/internal/sockstest/server_test.go

@@ -0,0 +1,103 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sockstest
+
+import (
+	"net"
+	"reflect"
+	"testing"
+
+	"golang.org/x/net/internal/socks"
+)
+
+func TestParseAuthRequest(t *testing.T) {
+	for i, tt := range []struct {
+		wire []byte
+		req  *AuthRequest
+	}{
+		{
+			[]byte{0x05, 0x00},
+			&AuthRequest{
+				socks.Version5,
+				nil,
+			},
+		},
+		{
+			[]byte{0x05, 0x01, 0xff},
+			&AuthRequest{
+				socks.Version5,
+				[]socks.AuthMethod{
+					socks.AuthMethodNoAcceptableMethods,
+				},
+			},
+		},
+		{
+			[]byte{0x05, 0x02, 0x00, 0xff},
+			&AuthRequest{
+				socks.Version5,
+				[]socks.AuthMethod{
+					socks.AuthMethodNotRequired,
+					socks.AuthMethodNoAcceptableMethods,
+				},
+			},
+		},
+
+		// corrupted requests
+		{nil, nil},
+		{[]byte{0x00, 0x01}, nil},
+		{[]byte{0x06, 0x00}, nil},
+		{[]byte{0x05, 0x02, 0x00}, nil},
+	} {
+		req, err := ParseAuthRequest(tt.wire)
+		if !reflect.DeepEqual(req, tt.req) {
+			t.Errorf("#%d: got %v, %v; want %v", i, req, err, tt.req)
+			continue
+		}
+	}
+}
+
+func TestParseCmdRequest(t *testing.T) {
+	for i, tt := range []struct {
+		wire []byte
+		req  *CmdRequest
+	}{
+		{
+			[]byte{0x05, 0x01, 0x00, 0x01, 192, 0, 2, 1, 0x17, 0x4b},
+			&CmdRequest{
+				socks.Version5,
+				socks.CmdConnect,
+				socks.Addr{
+					IP:   net.IP{192, 0, 2, 1},
+					Port: 5963,
+				},
+			},
+		},
+		{
+			[]byte{0x05, 0x01, 0x00, 0x03, 0x04, 'F', 'Q', 'D', 'N', 0x17, 0x4b},
+			&CmdRequest{
+				socks.Version5,
+				socks.CmdConnect,
+				socks.Addr{
+					Name: "FQDN",
+					Port: 5963,
+				},
+			},
+		},
+
+		// corrupted requests
+		{nil, nil},
+		{[]byte{0x05}, nil},
+		{[]byte{0x06, 0x01, 0x00, 0x01, 192, 0, 2, 2, 0x17, 0x4b}, nil},
+		{[]byte{0x05, 0x01, 0xff, 0x01, 192, 0, 2, 3}, nil},
+		{[]byte{0x05, 0x01, 0x00, 0x01, 192, 0, 2, 4}, nil},
+		{[]byte{0x05, 0x01, 0x00, 0x03, 0x04, 'F', 'Q', 'D', 'N'}, nil},
+	} {
+		req, err := ParseCmdRequest(tt.wire)
+		if !reflect.DeepEqual(req, tt.req) {
+			t.Errorf("#%d: got %v, %v; want %v", i, req, err, tt.req)
+			continue
+		}
+	}
+}

+ 5 - 5
vendor/golang.org/x/net/ipv4/control.go

@@ -83,14 +83,14 @@ func (cm *ControlMessage) Parse(b []byte) error {
 		if lvl != iana.ProtocolIP {
 		if lvl != iana.ProtocolIP {
 			continue
 			continue
 		}
 		}
-		switch typ {
-		case ctlOpts[ctlTTL].name:
+		switch {
+		case typ == ctlOpts[ctlTTL].name && l >= ctlOpts[ctlTTL].length:
 			ctlOpts[ctlTTL].parse(cm, m.Data(l))
 			ctlOpts[ctlTTL].parse(cm, m.Data(l))
-		case ctlOpts[ctlDst].name:
+		case typ == ctlOpts[ctlDst].name && l >= ctlOpts[ctlDst].length:
 			ctlOpts[ctlDst].parse(cm, m.Data(l))
 			ctlOpts[ctlDst].parse(cm, m.Data(l))
-		case ctlOpts[ctlInterface].name:
+		case typ == ctlOpts[ctlInterface].name && l >= ctlOpts[ctlInterface].length:
 			ctlOpts[ctlInterface].parse(cm, m.Data(l))
 			ctlOpts[ctlInterface].parse(cm, m.Data(l))
-		case ctlOpts[ctlPacketInfo].name:
+		case typ == ctlOpts[ctlPacketInfo].name && l >= ctlOpts[ctlPacketInfo].length:
 			ctlOpts[ctlPacketInfo].parse(cm, m.Data(l))
 			ctlOpts[ctlPacketInfo].parse(cm, m.Data(l))
 		}
 		}
 	}
 	}

+ 21 - 0
vendor/golang.org/x/net/ipv4/control_test.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.
+
+package ipv4_test
+
+import (
+	"testing"
+
+	"golang.org/x/net/ipv4"
+)
+
+func TestControlMessageParseWithFuzz(t *testing.T) {
+	var cm ipv4.ControlMessage
+	for _, fuzz := range []string{
+		"\f\x00\x00\x00\x00\x00\x00\x00\x14\x00\x00\x00",
+		"\f\x00\x00\x00\x00\x00\x00\x00\x1a\x00\x00\x00",
+	} {
+		cm.Parse([]byte(fuzz))
+	}
+}

+ 2 - 2
vendor/golang.org/x/net/ipv4/gen.go

@@ -72,7 +72,7 @@ var registries = []struct {
 	parse func(io.Writer, io.Reader) error
 	parse func(io.Writer, io.Reader) error
 }{
 }{
 	{
 	{
-		"http://www.iana.org/assignments/icmp-parameters/icmp-parameters.xml",
+		"https://www.iana.org/assignments/icmp-parameters/icmp-parameters.xml",
 		parseICMPv4Parameters,
 		parseICMPv4Parameters,
 	},
 	},
 }
 }
@@ -80,7 +80,7 @@ var registries = []struct {
 func geniana() error {
 func geniana() error {
 	var bb bytes.Buffer
 	var bb bytes.Buffer
 	fmt.Fprintf(&bb, "// go generate gen.go\n")
 	fmt.Fprintf(&bb, "// go generate gen.go\n")
-	fmt.Fprintf(&bb, "// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n\n")
+	fmt.Fprintf(&bb, "// Code generated by the command above; DO NOT EDIT.\n\n")
 	fmt.Fprintf(&bb, "package ipv4\n\n")
 	fmt.Fprintf(&bb, "package ipv4\n\n")
 	for _, r := range registries {
 	for _, r := range registries {
 		resp, err := http.Get(r.url)
 		resp, err := http.Get(r.url)

Some files were not shown because too many files changed in this diff