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:
 - name: github.com/armon/go-socks5
   version: e75332964ef517daa070d7c38a9466a0d687e0a5
@@ -71,11 +71,13 @@ imports:
   - twofish
   - xtea
 - name: golang.org/x/net
-  version: e4fa1c5465ad6111f206fc92186b8c83d64adbe1
+  version: 640f4622ab692b87c2f3a94265e6f579fe38263d
   subpackages:
   - bpf
   - context
   - internal/iana
   - internal/socket
+  - internal/socks
   - ipv4
+  - proxy
 testImports: []

+ 1 - 1
glide.yaml

@@ -58,7 +58,7 @@ import:
   - twofish
   - xtea
 - package: golang.org/x/net
-  version: e4fa1c5465ad6111f206fc92186b8c83d64adbe1
+  version: 640f4622ab692b87c2f3a94265e6f579fe38263d
   subpackages:
   - bpf
   - 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!
 
-
 ## Filing issues
 
 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.
 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)
 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
 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)
 }
 
-// String returns the the instruction in assembler notation.
+// String returns the instruction in assembler notation.
 func (a LoadConstant) String() string {
 	switch a.Dst {
 	case RegA:
@@ -224,7 +224,7 @@ func (a LoadScratch) Assemble() (RawInstruction, error) {
 	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 {
 	switch a.Dst {
 	case RegA:
@@ -248,7 +248,7 @@ func (a LoadAbsolute) Assemble() (RawInstruction, error) {
 	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 {
 	switch a.Size {
 	case 1: // byte
@@ -277,7 +277,7 @@ func (a LoadIndirect) Assemble() (RawInstruction, error) {
 	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 {
 	switch a.Size {
 	case 1: // byte
@@ -306,7 +306,7 @@ func (a LoadMemShift) Assemble() (RawInstruction, error) {
 	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 {
 	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))
 }
 
-// String returns the the instruction in assembler notation.
+// String returns the instruction in assembler notation.
 func (a LoadExtension) String() string {
 	switch a.Num {
 	case ExtLen:
@@ -392,7 +392,7 @@ func (a StoreScratch) Assemble() (RawInstruction, error) {
 	}, nil
 }
 
-// String returns the the instruction in assembler notation.
+// String returns the instruction in assembler notation.
 func (a StoreScratch) String() string {
 	switch a.Src {
 	case RegA:
@@ -418,7 +418,7 @@ func (a ALUOpConstant) Assemble() (RawInstruction, error) {
 	}, nil
 }
 
-// String returns the the instruction in assembler notation.
+// String returns the instruction in assembler notation.
 func (a ALUOpConstant) String() string {
 	switch a.Op {
 	case ALUOpAdd:
@@ -458,7 +458,7 @@ func (a ALUOpX) Assemble() (RawInstruction, error) {
 	}, nil
 }
 
-// String returns the the instruction in assembler notation.
+// String returns the instruction in assembler notation.
 func (a ALUOpX) String() string {
 	switch a.Op {
 	case ALUOpAdd:
@@ -496,7 +496,7 @@ func (a NegateA) Assemble() (RawInstruction, error) {
 	}, nil
 }
 
-// String returns the the instruction in assembler notation.
+// String returns the instruction in assembler notation.
 func (a NegateA) String() string {
 	return fmt.Sprintf("neg")
 }
@@ -514,7 +514,7 @@ func (a Jump) Assemble() (RawInstruction, error) {
 	}, nil
 }
 
-// String returns the the instruction in assembler notation.
+// String returns the instruction in assembler notation.
 func (a Jump) String() string {
 	return fmt.Sprintf("ja %d", a.Skip)
 }
@@ -566,7 +566,7 @@ func (a JumpIf) Assemble() (RawInstruction, error) {
 	}, nil
 }
 
-// String returns the the instruction in assembler notation.
+// String returns the instruction in assembler notation.
 func (a JumpIf) String() string {
 	switch a.Cond {
 	// K == A
@@ -621,7 +621,7 @@ func (a RetA) Assemble() (RawInstruction, error) {
 	}, nil
 }
 
-// String returns the the instruction in assembler notation.
+// String returns the instruction in assembler notation.
 func (a RetA) String() string {
 	return fmt.Sprintf("ret a")
 }
@@ -639,7 +639,7 @@ func (a RetConstant) Assemble() (RawInstruction, error) {
 	}, nil
 }
 
-// String returns the the instruction in assembler notation.
+// String returns the instruction in assembler notation.
 func (a RetConstant) String() string {
 	return fmt.Sprintf("ret #%d", a.Val)
 }
@@ -654,7 +654,7 @@ func (a TXA) Assemble() (RawInstruction, error) {
 	}, nil
 }
 
-// String returns the the instruction in assembler notation.
+// String returns the instruction in assembler notation.
 func (a TXA) String() string {
 	return fmt.Sprintf("txa")
 }
@@ -669,7 +669,7 @@ func (a TAX) Assemble() (RawInstruction, error) {
 	}, nil
 }
 
-// String returns the the instruction in assembler notation.
+// String returns the instruction in assembler notation.
 func (a TAX) String() string {
 	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,
 // cancelation signals, and other request-scoped values across API boundaries
 // 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
 // servers should accept a Context. The chain of function calls between must
@@ -36,103 +38,6 @@
 // Contexts.
 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
 // values, and has no deadline. It is typically used by the main function,
 // initialization, and tests, and as the top-level Context for incoming
@@ -149,8 +54,3 @@ func Background() Context {
 func TODO() Context {
 	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"
 )
 
+// This example passes a context with a timeout to tell a blocking function that
+// it should abandon its work after the timeout elapses.
 func ExampleWithTimeout() {
 	// Pass a context with a timeout to tell a blocking function that it
 	// should abandon its work after the timeout elapses.
-	ctx, _ := context.WithTimeout(context.Background(), 100*time.Millisecond)
+	ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond)
+	defer cancel()
+
 	select {
-	case <-time.After(200 * time.Millisecond):
+	case <-time.After(1 * time.Second):
 		fmt.Println("overslept")
 	case <-ctx.Done():
 		fmt.Println(ctx.Err()) // prints "context deadline exceeded"
 	}
+
 	// Output:
 	// 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
 
 import (
+	"bytes"
 	"fmt"
-	"net"
 	"reflect"
 	"strings"
 	"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 {
 	s := fmt.Sprintf("Message: %#v\n", &m.Header)
 	if len(m.Questions) > 0 {
@@ -41,15 +57,23 @@ func (m *Message) String() string {
 	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) {
 	want := Question{
-		Name:  ".",
+		Name:  mustNewName("."),
 		Type:  TypeA,
 		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 {
-		t.Fatal("Packing failed:", err)
+		t.Fatal("Question.pack() =", err)
 	}
 	var p Parser
 	p.msg = buf
@@ -58,13 +82,39 @@ func TestQuestionPackUnpack(t *testing.T) {
 	p.off = 1
 	got, err := p.Question()
 	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) {
-		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) {
-		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
 		err  error
 	}{
-		{"", ".", nil},
+		{"", "", errNonCanonicalName},
 		{".", ".", nil},
-		{"google..com", "", errZeroSegLen},
-		{"google.com", "google.com.", nil},
+		{"google..com", "", errNonCanonicalName},
+		{"google.com", "", errNonCanonicalName},
 		{"google..com.", "", errZeroSegLen},
 		{"google.com.", "google.com.", nil},
 		{".google.com.", "", errZeroSegLen},
@@ -86,29 +136,113 @@ func TestNamePackUnpack(t *testing.T) {
 	}
 
 	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 {
-			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
 		}
 		if test.err != nil {
 			continue
 		}
-		got, n, err := unpackName(buf, 0)
+		var got Name
+		n, err := got.unpack(buf, 0)
 		if err != nil {
-			t.Errorf("Unpacking for %s failed: %v", test.in, err)
+			t.Errorf("%q.unpack() = %v", test.in, err)
 			continue
 		}
 		if n != len(buf) {
 			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,
 				n,
 				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{
 				{
-					Name:  ".",
+					Name:  mustNewName("."),
 					Type:  TypeAAAA,
 					Class: ClassINET,
 				},
@@ -132,15 +266,49 @@ func TestDNSPackUnpack(t *testing.T) {
 	for i, want := range wants {
 		b, err := want.Pack()
 		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
 		err = got.Unpack(b)
 		if err != nil {
-			t.Fatalf("%d: unpacking failed: %v", i, err)
+			t.Fatalf("%d: Message.Unapck() = %v", i, err)
 		}
 		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()
 	buf, err := msg.Pack()
 	if err != nil {
-		t.Fatal("Packing large test message:", err)
+		t.Fatal("Message.Pack() =", err)
 	}
 	var p Parser
 	if _, err := p.Start(buf); err != nil {
-		t.Fatal(err)
+		t.Fatal("Parser.Start(non-nil) =", err)
 	}
 
 	tests := []struct {
@@ -168,12 +336,75 @@ func TestSkipAll(t *testing.T) {
 	for _, test := range tests {
 		for i := 1; i <= 3; i++ {
 			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) {
 	var p Parser
 
@@ -188,7 +419,7 @@ func TestSkipNotStarted(t *testing.T) {
 	}
 	for _, test := range tests {
 		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 {
 		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) {
-	want := &TXTResource{
-		ResourceHeader: ResourceHeader{
-			Name:  "foo.bar.example.com.",
+	want := Resource{
+		ResourceHeader{
+			Name:  mustNewName("foo.bar.example.com."),
 			Type:  TypeTXT,
 			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 {
-		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 {
-		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 {
-		t.Fatal("Unpacking failed:", err)
+		t.Fatal("unpackResourceBody() =", err)
 	}
+	got.Body = body
 	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) {
-		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{
 		Header: Header{Response: true, Authoritative: true},
 		Questions: []Question{
 			{
-				Name:  "foo.bar.example.com.",
-				Type:  TypeA,
-				Class: ClassINET,
-			},
-			{
-				Name:  "bar.example.com.",
+				Name:  name,
 				Type:  TypeA,
 				Class: ClassINET,
 			},
 		},
 		Answers: []Resource{
-			&AResource{
-				ResourceHeader: ResourceHeader{
-					Name:  "foo.bar.example.com.",
-					Type:  TypeA,
+			{
+				ResourceHeader{
+					Name:  name,
 					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,
 				},
-				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()
 	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
 	if _, err := p.Start(buf); err != nil {
-		panic(err)
+		tb.Fatal("Parser.Start(non-nil) =", err)
 	}
 
 	for {
-		q, err := p.Question()
+		_, err := p.Question()
 		if err == ErrSectionDone {
 			break
 		}
 		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 {
 		h, err := p.AnswerHeader()
 		if err == ErrSectionDone {
 			break
 		}
 		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 {
+	name := mustNewName("foo.bar.example.com.")
 	return Message{
 		Header: Header{Response: true, Authoritative: true},
 		Questions: []Question{
 			{
-				Name:  "foo.bar.example.com.",
+				Name:  name,
 				Type:  TypeA,
 				Class: ClassINET,
 			},
 		},
 		Answers: []Resource{
-			&AResource{
-				ResourceHeader: ResourceHeader{
-					Name:  "foo.bar.example.com.",
+			{
+				ResourceHeader{
+					Name:  name,
 					Type:  TypeA,
 					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,
 					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{
-			&NSResource{
-				ResourceHeader: ResourceHeader{
-					Name:  "foo.bar.example.com.",
+			{
+				ResourceHeader{
+					Name:  name,
 					Type:  TypeNS,
 					Class: ClassINET,
 				},
-				NS: "ns1.example.com.",
+				&NSResource{mustNewName("ns1.example.com.")},
 			},
-			&NSResource{
-				ResourceHeader: ResourceHeader{
-					Name:  "foo.bar.example.com.",
+			{
+				ResourceHeader{
+					Name:  name,
 					Type:  TypeNS,
 					Class: ClassINET,
 				},
-				NS: "ns2.example.com.",
+				&NSResource{mustNewName("ns2.example.com.")},
 			},
 		},
 		Additionals: []Resource{
-			&TXTResource{
-				ResourceHeader: ResourceHeader{
-					Name:  "foo.bar.example.com.",
+			{
+				ResourceHeader{
+					Name:  name,
 					Type:  TypeTXT,
 					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,
 					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
 
-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 (
+	"bytes"
 	"flag"
 	"fmt"
+	"go/format"
+	"io/ioutil"
 	"math/rand"
 	"os"
 	"sort"
@@ -42,6 +42,18 @@ func identifier(s string) string {
 
 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() {
 	flag.Parse()
 
@@ -52,32 +64,31 @@ func main() {
 	all = append(all, extra...)
 	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
-	// compute max len too
-	maxLen := 0
 	w := 0
 	for _, s := range all {
 		if w == 0 || all[w-1] != s {
-			if maxLen < len(s) {
-				maxLen = len(s)
-			}
 			all[w] = s
 			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.
 	var best *table
 	for i := 0; i < 1000000; i++ {
@@ -163,36 +174,46 @@ func main() {
 		atom[s] = uint32(off<<8 | len(s))
 	}
 
+	var buf bytes.Buffer
 	// 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 {
-		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 {
 		if s == "" {
 			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
 
-	fmt.Printf("const atomText =\n")
+	fmt.Fprintln(&buf, "const atomText =")
 	textsize := len(text)
 	for len(text) > 60 {
-		fmt.Printf("\t%q +\n", text[:60])
+		fmt.Fprintf(&buf, "\t%q +\n", 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
@@ -285,8 +306,10 @@ func (t *table) push(i uint32, depth int) bool {
 
 // The lists of element names and attribute keys were taken from
 // 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{
 	"a",
 	"abbr",
@@ -349,6 +372,7 @@ var elements = []string{
 	"legend",
 	"li",
 	"link",
+	"main",
 	"map",
 	"mark",
 	"menu",
@@ -364,6 +388,7 @@ var elements = []string{
 	"output",
 	"p",
 	"param",
+	"picture",
 	"pre",
 	"progress",
 	"q",
@@ -375,6 +400,7 @@ var elements = []string{
 	"script",
 	"section",
 	"select",
+	"slot",
 	"small",
 	"source",
 	"span",
@@ -403,14 +429,21 @@ var elements = []string{
 }
 
 // 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{
 	"abbr",
 	"accept",
 	"accept-charset",
 	"accesskey",
 	"action",
+	"allowfullscreen",
+	"allowpaymentrequest",
+	"allowusermedia",
 	"alt",
+	"as",
 	"async",
 	"autocomplete",
 	"autofocus",
@@ -420,6 +453,7 @@ var attributes = []string{
 	"checked",
 	"cite",
 	"class",
+	"color",
 	"cols",
 	"colspan",
 	"command",
@@ -457,6 +491,8 @@ var attributes = []string{
 	"icon",
 	"id",
 	"inputmode",
+	"integrity",
+	"is",
 	"ismap",
 	"itemid",
 	"itemprop",
@@ -481,16 +517,20 @@ var attributes = []string{
 	"multiple",
 	"muted",
 	"name",
+	"nomodule",
+	"nonce",
 	"novalidate",
 	"open",
 	"optimum",
 	"pattern",
 	"ping",
 	"placeholder",
+	"playsinline",
 	"poster",
 	"preload",
 	"radiogroup",
 	"readonly",
+	"referrerpolicy",
 	"rel",
 	"required",
 	"reversed",
@@ -507,10 +547,13 @@ var attributes = []string{
 	"sizes",
 	"sortable",
 	"sorted",
+	"slot",
 	"span",
+	"spellcheck",
 	"src",
 	"srcdoc",
 	"srclang",
+	"srcset",
 	"start",
 	"step",
 	"style",
@@ -520,16 +563,22 @@ var attributes = []string{
 	"translate",
 	"type",
 	"typemustmatch",
+	"updateviacache",
 	"usemap",
 	"value",
 	"width",
+	"workertype",
 	"wrap",
 }
 
+// "onautocomplete", "onautocompleteerror", "onmousewheel",
+// "onshow" and "onsort" have been removed from the spec,
+// but are kept here for backwards compatibility.
 var eventHandlers = []string{
 	"onabort",
 	"onautocomplete",
 	"onautocompleteerror",
+	"onauxclick",
 	"onafterprint",
 	"onbeforeprint",
 	"onbeforeunload",
@@ -541,11 +590,14 @@ var eventHandlers = []string{
 	"onclick",
 	"onclose",
 	"oncontextmenu",
+	"oncopy",
 	"oncuechange",
+	"oncut",
 	"ondblclick",
 	"ondrag",
 	"ondragend",
 	"ondragenter",
+	"ondragexit",
 	"ondragleave",
 	"ondragover",
 	"ondragstart",
@@ -565,18 +617,24 @@ var eventHandlers = []string{
 	"onload",
 	"onloadeddata",
 	"onloadedmetadata",
+	"onloadend",
 	"onloadstart",
 	"onmessage",
+	"onmessageerror",
 	"onmousedown",
+	"onmouseenter",
+	"onmouseleave",
 	"onmousemove",
 	"onmouseout",
 	"onmouseover",
 	"onmouseup",
 	"onmousewheel",
+	"onwheel",
 	"onoffline",
 	"ononline",
 	"onpagehide",
 	"onpageshow",
+	"onpaste",
 	"onpause",
 	"onplay",
 	"onplaying",
@@ -585,7 +643,9 @@ var eventHandlers = []string{
 	"onratechange",
 	"onreset",
 	"onresize",
+	"onrejectionhandled",
 	"onscroll",
+	"onsecuritypolicyviolation",
 	"onseeked",
 	"onseeking",
 	"onselect",
@@ -597,6 +657,7 @@ var eventHandlers = []string{
 	"onsuspend",
 	"ontimeupdate",
 	"ontoggle",
+	"onunhandledrejection",
 	"onunload",
 	"onvolumechange",
 	"onwaiting",
@@ -604,6 +665,7 @@ var eventHandlers = []string{
 
 // extra are ad-hoc values not covered by any of the lists above.
 var extra = []string{
+	"acronym",
 	"align",
 	"annotation",
 	"annotation-xml",
@@ -639,6 +701,8 @@ var extra = []string{
 	"plaintext",
 	"prompt",
 	"public",
+	"rb",
+	"rtc",
 	"spacer",
 	"strike",
 	"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
 
 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{
-	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
 
 var testAtomList = []string{
 	"a",
 	"abbr",
-	"abbr",
 	"accept",
 	"accept-charset",
 	"accesskey",
+	"acronym",
 	"action",
 	"address",
 	"align",
+	"allowfullscreen",
+	"allowpaymentrequest",
+	"allowusermedia",
 	"alt",
 	"annotation",
 	"annotation-xml",
 	"applet",
 	"area",
 	"article",
+	"as",
 	"aside",
 	"async",
 	"audio",
@@ -43,7 +49,6 @@ var testAtomList = []string{
 	"charset",
 	"checked",
 	"cite",
-	"cite",
 	"class",
 	"code",
 	"col",
@@ -52,7 +57,6 @@ var testAtomList = []string{
 	"cols",
 	"colspan",
 	"command",
-	"command",
 	"content",
 	"contenteditable",
 	"contextmenu",
@@ -60,7 +64,6 @@ var testAtomList = []string{
 	"coords",
 	"crossorigin",
 	"data",
-	"data",
 	"datalist",
 	"datetime",
 	"dd",
@@ -93,7 +96,6 @@ var testAtomList = []string{
 	"foreignObject",
 	"foreignobject",
 	"form",
-	"form",
 	"formaction",
 	"formenctype",
 	"formmethod",
@@ -128,6 +130,8 @@ var testAtomList = []string{
 	"input",
 	"inputmode",
 	"ins",
+	"integrity",
+	"is",
 	"isindex",
 	"ismap",
 	"itemid",
@@ -140,7 +144,6 @@ var testAtomList = []string{
 	"keytype",
 	"kind",
 	"label",
-	"label",
 	"lang",
 	"legend",
 	"li",
@@ -149,6 +152,7 @@ var testAtomList = []string{
 	"listing",
 	"loop",
 	"low",
+	"main",
 	"malignmark",
 	"manifest",
 	"map",
@@ -179,6 +183,8 @@ var testAtomList = []string{
 	"nobr",
 	"noembed",
 	"noframes",
+	"nomodule",
+	"nonce",
 	"noscript",
 	"novalidate",
 	"object",
@@ -187,6 +193,7 @@ var testAtomList = []string{
 	"onafterprint",
 	"onautocomplete",
 	"onautocompleteerror",
+	"onauxclick",
 	"onbeforeprint",
 	"onbeforeunload",
 	"onblur",
@@ -197,11 +204,14 @@ var testAtomList = []string{
 	"onclick",
 	"onclose",
 	"oncontextmenu",
+	"oncopy",
 	"oncuechange",
+	"oncut",
 	"ondblclick",
 	"ondrag",
 	"ondragend",
 	"ondragenter",
+	"ondragexit",
 	"ondragleave",
 	"ondragover",
 	"ondragstart",
@@ -221,9 +231,13 @@ var testAtomList = []string{
 	"onload",
 	"onloadeddata",
 	"onloadedmetadata",
+	"onloadend",
 	"onloadstart",
 	"onmessage",
+	"onmessageerror",
 	"onmousedown",
+	"onmouseenter",
+	"onmouseleave",
 	"onmousemove",
 	"onmouseout",
 	"onmouseover",
@@ -233,15 +247,18 @@ var testAtomList = []string{
 	"ononline",
 	"onpagehide",
 	"onpageshow",
+	"onpaste",
 	"onpause",
 	"onplay",
 	"onplaying",
 	"onpopstate",
 	"onprogress",
 	"onratechange",
+	"onrejectionhandled",
 	"onreset",
 	"onresize",
 	"onscroll",
+	"onsecuritypolicyviolation",
 	"onseeked",
 	"onseeking",
 	"onselect",
@@ -253,9 +270,11 @@ var testAtomList = []string{
 	"onsuspend",
 	"ontimeupdate",
 	"ontoggle",
+	"onunhandledrejection",
 	"onunload",
 	"onvolumechange",
 	"onwaiting",
+	"onwheel",
 	"open",
 	"optgroup",
 	"optimum",
@@ -264,9 +283,11 @@ var testAtomList = []string{
 	"p",
 	"param",
 	"pattern",
+	"picture",
 	"ping",
 	"placeholder",
 	"plaintext",
+	"playsinline",
 	"poster",
 	"pre",
 	"preload",
@@ -275,7 +296,9 @@ var testAtomList = []string{
 	"public",
 	"q",
 	"radiogroup",
+	"rb",
 	"readonly",
+	"referrerpolicy",
 	"rel",
 	"required",
 	"reversed",
@@ -283,6 +306,7 @@ var testAtomList = []string{
 	"rowspan",
 	"rp",
 	"rt",
+	"rtc",
 	"ruby",
 	"s",
 	"samp",
@@ -297,23 +321,23 @@ var testAtomList = []string{
 	"shape",
 	"size",
 	"sizes",
+	"slot",
 	"small",
 	"sortable",
 	"sorted",
 	"source",
 	"spacer",
 	"span",
-	"span",
 	"spellcheck",
 	"src",
 	"srcdoc",
 	"srclang",
+	"srcset",
 	"start",
 	"step",
 	"strike",
 	"strong",
 	"style",
-	"style",
 	"sub",
 	"summary",
 	"sup",
@@ -331,7 +355,6 @@ var testAtomList = []string{
 	"thead",
 	"time",
 	"title",
-	"title",
 	"tr",
 	"track",
 	"translate",
@@ -340,12 +363,14 @@ var testAtomList = []string{
 	"typemustmatch",
 	"u",
 	"ul",
+	"updateviacache",
 	"usemap",
 	"value",
 	"var",
 	"video",
 	"wbr",
 	"width",
+	"workertype",
 	"wrap",
 	"xmp",
 }

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

@@ -4,7 +4,7 @@
 
 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".
 // https://html.spec.whatwg.org/multipage/syntax.html#the-stack-of-open-elements
 var isSpecialElementMap = map[string]bool{
@@ -52,10 +52,12 @@ var isSpecialElementMap = map[string]bool{
 	"iframe":     true,
 	"img":        true,
 	"input":      true,
-	"isindex":    true,
+	"isindex":    true, // The 'isindex' element has been removed, but keep it for backwards compatibility.
+	"keygen":     true,
 	"li":         true,
 	"link":       true,
 	"listing":    true,
+	"main":       true,
 	"marquee":    true,
 	"menu":       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 {
 		tt := z.Next()
 		switch tt {
-		case ErrorToken:
+		case html.ErrorToken:
 			return z.Err()
-		case TextToken:
+		case html.TextToken:
 			if depth > 0 {
 				// emitBytes should copy the []byte it receives,
 				// if it doesn't process it immediately.
 				emitBytes(z.Text())
 			}
-		case StartTagToken, EndTagToken:
+		case html.StartTagToken, html.EndTagToken:
 			tn, _ := z.TagName()
 			if len(tn) == 1 && tn[0] == 'a' {
-				if tt == StartTagToken {
+				if tt == html.StartTagToken {
 					depth++
 				} else {
 					depth--

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

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

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

@@ -21,9 +21,10 @@ const (
 	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}
 
 // 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
 }
 
+// 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.
 func (s *nodeStack) insert(i int, n *Node) {
 	(*s) = append(*s, nil)
@@ -191,3 +202,19 @@ func (s *nodeStack) remove(n *Node) {
 	(*s)[j] = nil
 	*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
 	// doc is the document root element.
 	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
-	// Element pointers (section 12.2.3.4).
+	// Element pointers (section 12.2.4.4).
 	head, form *Node
-	// Other parsing state flags (section 12.2.3.5).
+	// Other parsing state flags (section 12.2.4.5).
 	scripting, framesetOK bool
+	// The stack of template insertion modes
+	templateStack insertionModeStack
 	// im is the current insertion mode.
 	im insertionMode
 	// originalIM is the insertion mode to go back to after completing a text
 	// or inTableText insertion mode.
 	originalIM insertionMode
 	// 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
 	// quirks is whether the parser is operating in "quirks mode."
 	quirks bool
@@ -56,7 +58,7 @@ func (p *parser) top() *Node {
 	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 (
 	defaultScopeStopTags = map[string][]a.Atom{
 		"":     {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
 // 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.
 //
 // 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
 				}
 			case tableScope:
-				if tagAtom == a.Html || tagAtom == a.Table {
+				if tagAtom == a.Html || tagAtom == a.Table || tagAtom == a.Template {
 					return -1
 				}
 			case selectScope:
@@ -162,17 +164,17 @@ func (p *parser) clearStackToContext(s scope) {
 		tagAtom := p.oe[i].DataAtom
 		switch s {
 		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]
 				return
 			}
 		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]
 				return
 			}
 		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]
 				return
 			}
@@ -183,7 +185,7 @@ func (p *parser) clearStackToContext(s scope) {
 }
 
 // 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.
 func (p *parser) generateImpliedEndTags(exceptions ...string) {
 	var i int
@@ -192,7 +194,7 @@ loop:
 		n := p.oe[i]
 		if n.Type == ElementNode {
 			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 {
 					if n.Data == except {
 						break loop
@@ -207,6 +209,27 @@ loop:
 	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
 // of open elements if it is an element 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.
-// Section 12.2.5.3, "foster parenting".
+// Section 12.2.6.1, "foster parenting".
 func (p *parser) fosterParent(n *Node) {
-	var table, parent, prev *Node
+	var table, parent, prev, template *Node
 	var i int
 	for i = len(p.oe) - 1; i >= 0; i-- {
 		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 {
 		// The foster parent is the html element.
 		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() {
 	tagAtom, attr := p.tok.DataAtom, p.tok.Attr
 	p.addElement()
@@ -351,7 +387,7 @@ findIdenticalElements:
 	p.afe = append(p.afe, p.top())
 }
 
-// Section 12.2.3.3.
+// Section 12.2.4.3.
 func (p *parser) clearActiveFormattingElements() {
 	for {
 		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() {
 	n := p.afe.top()
 	if n == nil {
@@ -390,12 +426,12 @@ func (p *parser) reconstructActiveFormattingElements() {
 	}
 }
 
-// Section 12.2.4.
+// Section 12.2.5.
 func (p *parser) acknowledgeSelfClosingTag() {
 	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
 // parser's fields depending on parser.tok (where ErrorToken means EOF).
 // 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
 // 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() {
 	if p.originalIM != nil {
 		panic("html: bad parser state: originalIM was set twice")
@@ -411,18 +447,38 @@ func (p *parser) setOriginalIM() {
 	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() {
 	for i := len(p.oe) - 1; i >= 0; i-- {
 		n := p.oe[i]
-		if i == 0 && p.context != nil {
+		last := i == 0
+		if last && p.context != nil {
 			n = p.context
 		}
 
 		switch n.DataAtom {
 		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
 		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
 		case a.Tr:
 			p.im = inRowIM
@@ -434,25 +490,37 @@ func (p *parser) resetInsertionMode() {
 			p.im = inColumnGroupIM
 		case a.Table:
 			p.im = inTableIM
+		case a.Template:
+			p.im = p.templateStack.top()
 		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:
 			p.im = inBodyIM
 		case a.Frameset:
 			p.im = inFramesetIM
 		case a.Html:
-			p.im = beforeHeadIM
+			if p.head == nil {
+				p.im = beforeHeadIM
+			} else {
+				p.im = afterHeadIM
+			}
 		default:
+			if last {
+				p.im = inBodyIM
+				return
+			}
 			continue
 		}
 		return
 	}
-	p.im = inBodyIM
 }
 
 const whitespace = " \t\r\n\f"
 
-// Section 12.2.5.4.1.
+// Section 12.2.6.4.1.
 func initialIM(p *parser) bool {
 	switch p.tok.Type {
 	case TextToken:
@@ -479,7 +547,7 @@ func initialIM(p *parser) bool {
 	return false
 }
 
-// Section 12.2.5.4.2.
+// Section 12.2.6.4.2.
 func beforeHTMLIM(p *parser) bool {
 	switch p.tok.Type {
 	case DoctypeToken:
@@ -517,7 +585,7 @@ func beforeHTMLIM(p *parser) bool {
 	return false
 }
 
-// Section 12.2.5.4.3.
+// Section 12.2.6.4.3.
 func beforeHeadIM(p *parser) bool {
 	switch p.tok.Type {
 	case TextToken:
@@ -560,7 +628,7 @@ func beforeHeadIM(p *parser) bool {
 	return false
 }
 
-// Section 12.2.5.4.4.
+// Section 12.2.6.4.4.
 func inHeadIM(p *parser) bool {
 	switch p.tok.Type {
 	case TextToken:
@@ -590,19 +658,36 @@ func inHeadIM(p *parser) bool {
 		case a.Head:
 			// Ignore the token.
 			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:
 		switch p.tok.DataAtom {
 		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
 			return true
 		case a.Body, a.Html, a.Br:
 			p.parseImpliedToken(EndTagToken, a.Head, a.Head.String())
 			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:
 			// Ignore the token.
 			return true
@@ -622,7 +707,7 @@ func inHeadIM(p *parser) bool {
 	return false
 }
 
-// Section 12.2.5.4.6.
+// Section 12.2.6.4.6.
 func afterHeadIM(p *parser) bool {
 	switch p.tok.Type {
 	case TextToken:
@@ -648,7 +733,7 @@ func afterHeadIM(p *parser) bool {
 			p.addElement()
 			p.im = inFramesetIM
 			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)
 			defer p.oe.remove(p.head)
 			return inHeadIM(p)
@@ -660,6 +745,8 @@ func afterHeadIM(p *parser) bool {
 		switch p.tok.DataAtom {
 		case a.Body, a.Html, a.Br:
 			// Drop down to creating an implied <body> tag.
+		case a.Template:
+			return inHeadIM(p)
 		default:
 			// Ignore the token.
 			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 {
 	switch p.tok.Type {
 	case TextToken:
@@ -727,10 +814,16 @@ func inBodyIM(p *parser) bool {
 	case StartTagToken:
 		switch p.tok.DataAtom {
 		case a.Html:
+			if p.oe.contains(a.Template) {
+				return true
+			}
 			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)
 		case a.Body:
+			if p.oe.contains(a.Template) {
+				return true
+			}
 			if len(p.oe) >= 2 {
 				body := p.oe[1]
 				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.
 			p.framesetOK = false
 		case a.Form:
-			if p.form == nil {
+			if p.oe.contains(a.Template) || p.form == nil {
 				p.popUntil(buttonScope, a.P)
 				p.addElement()
 				p.form = p.top()
@@ -952,11 +1045,16 @@ func inBodyIM(p *parser) bool {
 			}
 			p.reconstructActiveFormattingElements()
 			p.addElement()
-		case a.Rp, a.Rt:
+		case a.Rb, a.Rtc:
 			if p.elementInScope(defaultScope, a.Ruby) {
 				p.generateImpliedEndTags()
 			}
 			p.addElement()
+		case a.Rp, a.Rt:
+			if p.elementInScope(defaultScope, a.Ruby) {
+				p.generateImpliedEndTags("rtc")
+			}
+			p.addElement()
 		case a.Math, a.Svg:
 			p.reconstructActiveFormattingElements()
 			if p.tok.DataAtom == a.Math {
@@ -972,7 +1070,13 @@ func inBodyIM(p *parser) bool {
 				p.acknowledgeSelfClosingTag()
 			}
 			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.
 		default:
 			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:
 			p.popUntil(defaultScope, p.tok.DataAtom)
 		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:
 			if !p.elementInScope(buttonScope, a.P) {
 				p.parseImpliedToken(StartTagToken, a.P, a.P.String())
@@ -1022,6 +1139,8 @@ func inBodyIM(p *parser) bool {
 		case a.Br:
 			p.tok.Type = StartTagToken
 			return false
+		case a.Template:
+			return inHeadIM(p)
 		default:
 			p.inBodyEndTagOther(p.tok.DataAtom)
 		}
@@ -1030,6 +1149,21 @@ func inBodyIM(p *parser) bool {
 			Type: CommentNode,
 			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
@@ -1135,6 +1269,12 @@ func (p *parser) inBodyEndTagFormatting(tagAtom a.Atom) {
 		switch commonAncestor.DataAtom {
 		case a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr:
 			p.fosterParent(lastNode)
+		case a.Template:
+			// TODO: remove namespace checking
+			if commonAncestor.Namespace == "html" {
+				commonAncestor = commonAncestor.LastChild
+			}
+			fallthrough
 		default:
 			commonAncestor.AppendChild(lastNode)
 		}
@@ -1160,7 +1300,7 @@ func (p *parser) inBodyEndTagFormatting(tagAtom a.Atom) {
 }
 
 // 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
 func (p *parser) inBodyEndTagOther(tagAtom a.Atom) {
 	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 {
 	switch p.tok.Type {
 	case ErrorToken:
@@ -1203,7 +1343,7 @@ func textIM(p *parser) bool {
 	return p.tok.Type == EndTagToken
 }
 
-// Section 12.2.5.4.9.
+// Section 12.2.6.4.9.
 func inTableIM(p *parser) bool {
 	switch p.tok.Type {
 	case ErrorToken:
@@ -1249,7 +1389,7 @@ func inTableIM(p *parser) bool {
 			}
 			// Ignore the token.
 			return true
-		case a.Style, a.Script:
+		case a.Style, a.Script, a.Template:
 			return inHeadIM(p)
 		case a.Input:
 			for _, t := range p.tok.Attr {
@@ -1261,7 +1401,7 @@ func inTableIM(p *parser) bool {
 			}
 			// Otherwise drop down to the default action.
 		case a.Form:
-			if p.form != nil {
+			if p.oe.contains(a.Template) || p.form != nil {
 				// Ignore the token.
 				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:
 			// Ignore the token.
 			return true
+		case a.Template:
+			return inHeadIM(p)
 		}
 	case CommentToken:
 		p.addChild(&Node{
@@ -1309,7 +1451,7 @@ func inTableIM(p *parser) bool {
 	return inBodyIM(p)
 }
 
-// Section 12.2.5.4.11.
+// Section 12.2.6.4.11.
 func inCaptionIM(p *parser) bool {
 	switch p.tok.Type {
 	case StartTagToken:
@@ -1355,7 +1497,7 @@ func inCaptionIM(p *parser) bool {
 	return inBodyIM(p)
 }
 
-// Section 12.2.5.4.12.
+// Section 12.2.6.4.12.
 func inColumnGroupIM(p *parser) bool {
 	switch p.tok.Type {
 	case TextToken:
@@ -1386,11 +1528,13 @@ func inColumnGroupIM(p *parser) bool {
 			p.oe.pop()
 			p.acknowledgeSelfClosingTag()
 			return true
+		case a.Template:
+			return inHeadIM(p)
 		}
 	case EndTagToken:
 		switch p.tok.DataAtom {
 		case a.Colgroup:
-			if p.oe.top().DataAtom != a.Html {
+			if p.oe.top().DataAtom == a.Colgroup {
 				p.oe.pop()
 				p.im = inTableIM
 			}
@@ -1398,17 +1542,19 @@ func inColumnGroupIM(p *parser) bool {
 		case a.Col:
 			// Ignore the token.
 			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 {
 	switch p.tok.Type {
 	case StartTagToken:
@@ -1460,7 +1606,7 @@ func inTableBodyIM(p *parser) bool {
 	return inTableIM(p)
 }
 
-// Section 12.2.5.4.14.
+// Section 12.2.6.4.14.
 func inRowIM(p *parser) bool {
 	switch p.tok.Type {
 	case StartTagToken:
@@ -1511,7 +1657,7 @@ func inRowIM(p *parser) bool {
 	return inTableIM(p)
 }
 
-// Section 12.2.5.4.15.
+// Section 12.2.6.4.15.
 func inCellIM(p *parser) bool {
 	switch p.tok.Type {
 	case StartTagToken:
@@ -1560,7 +1706,7 @@ func inCellIM(p *parser) bool {
 	return inBodyIM(p)
 }
 
-// Section 12.2.5.4.16.
+// Section 12.2.6.4.16.
 func inSelectIM(p *parser) bool {
 	switch p.tok.Type {
 	case ErrorToken:
@@ -1597,7 +1743,7 @@ func inSelectIM(p *parser) bool {
 			p.tokenizer.NextIsNotRawText()
 			// Ignore the token.
 			return true
-		case a.Script:
+		case a.Script, a.Template:
 			return inHeadIM(p)
 		}
 	case EndTagToken:
@@ -1618,6 +1764,8 @@ func inSelectIM(p *parser) bool {
 			if p.popUntil(selectScope, a.Select) {
 				p.resetInsertionMode()
 			}
+		case a.Template:
+			return inHeadIM(p)
 		}
 	case CommentToken:
 		p.addChild(&Node{
@@ -1632,7 +1780,7 @@ func inSelectIM(p *parser) bool {
 	return true
 }
 
-// Section 12.2.5.4.17.
+// Section 12.2.6.4.17.
 func inSelectInTableIM(p *parser) bool {
 	switch p.tok.Type {
 	case StartTagToken, EndTagToken:
@@ -1650,7 +1798,62 @@ func inSelectInTableIM(p *parser) bool {
 	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 {
 	switch p.tok.Type {
 	case ErrorToken:
@@ -1688,7 +1891,7 @@ func afterBodyIM(p *parser) bool {
 	return false
 }
 
-// Section 12.2.5.4.19.
+// Section 12.2.6.4.20.
 func inFramesetIM(p *parser) bool {
 	switch p.tok.Type {
 	case CommentToken:
@@ -1720,6 +1923,11 @@ func inFramesetIM(p *parser) bool {
 			p.acknowledgeSelfClosingTag()
 		case a.Noframes:
 			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:
 		switch p.tok.DataAtom {
@@ -1738,7 +1946,7 @@ func inFramesetIM(p *parser) bool {
 	return true
 }
 
-// Section 12.2.5.4.20.
+// Section 12.2.6.4.21.
 func afterFramesetIM(p *parser) bool {
 	switch p.tok.Type {
 	case CommentToken:
@@ -1777,7 +1985,7 @@ func afterFramesetIM(p *parser) bool {
 	return true
 }
 
-// Section 12.2.5.4.21.
+// Section 12.2.6.4.22.
 func afterAfterBodyIM(p *parser) bool {
 	switch p.tok.Type {
 	case ErrorToken:
@@ -1806,7 +2014,7 @@ func afterAfterBodyIM(p *parser) bool {
 	return false
 }
 
-// Section 12.2.5.4.22.
+// Section 12.2.6.4.23.
 func afterAfterFramesetIM(p *parser) bool {
 	switch p.tok.Type {
 	case CommentToken:
@@ -1844,7 +2052,7 @@ func afterAfterFramesetIM(p *parser) bool {
 
 const whitespaceOrNUL = whitespace + "\x00"
 
-// Section 12.2.5.5.
+// Section 12.2.6.5
 func parseForeignContent(p *parser) bool {
 	switch p.tok.Type {
 	case TextToken:
@@ -1924,7 +2132,7 @@ func parseForeignContent(p *parser) bool {
 	return true
 }
 
-// Section 12.2.5.
+// Section 12.2.6.
 func (p *parser) inForeignContent() bool {
 	if len(p.oe) == 0 {
 		return false
@@ -2064,6 +2272,9 @@ func ParseFragment(r io.Reader, context *Node) ([]*Node, error) {
 	}
 	p.doc.AppendChild(root)
 	p.oe = nodeStack{root}
+	if context != nil && context.DataAtom == a.Template {
+		p.templateStack = append(p.templateStack, inTemplateIM)
+	}
 	p.resetInsertionMode()
 
 	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 {
 	dumpIndent(w, level)
+	level++
 	switch n.Type {
 	case ErrorNode:
 		return errors.New("unexpected ErrorNode")
@@ -140,13 +141,19 @@ func dumpLevel(w io.Writer, n *Node, level int) error {
 		sort.Sort(attr)
 		for _, a := range attr {
 			io.WriteString(w, "\n")
-			dumpIndent(w, level+1)
+			dumpIndent(w, level)
 			if a.Namespace != "" {
 				fmt.Fprintf(w, `%s %s="%s"`, a.Namespace, a.Key, a.Val)
 			} else {
 				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:
 		fmt.Fprintf(w, `"%s"`, n.Data)
 	case CommentNode:
@@ -176,7 +183,7 @@ func dumpLevel(w io.Writer, n *Node, level int) error {
 	}
 	io.WriteString(w, "\n")
 	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
 		}
 	}
@@ -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) {
 	buf, err := ioutil.ReadFile("testdata/go1.html")
 	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
 }
 
-// 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 {
 	t := Token{Type: 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
 
 // 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 (
 	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) {
 	for _, c := range badCiphers {
 		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) {
 	res, err := rt.t.RoundTrip(req)
-	if err == ErrNoCachedConn {
+	if isNoCachedConnError(err) {
 		return nil, http.ErrSkipAltProtocol
 	}
 	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" }
 
-// 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
-// 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 {
-	Code   ErrCode
-	Reason string
+	Code   ErrCode // the ConnectionError error code
+	Reason string  // additional reason
 }
 
 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 {
 	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{
 		{":status", "200"},
 		{"x-foo", "bar"},
-		{"content-type", "text/plain; charset=utf-8"},
 		{"content-length", "0"},
 	}
 	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-secret.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 (
 	"bytes"
+	"context"
 	"crypto/tls"
 	"flag"
 	"fmt"
@@ -19,7 +20,6 @@ import (
 	"log"
 	"net"
 	"net/http"
-	"os"
 	"path"
 	"regexp"
 	"runtime"
@@ -28,7 +28,9 @@ import (
 	"sync"
 	"time"
 
+	"cloud.google.com/go/storage"
 	"go4.org/syncutil/singleflight"
+	"golang.org/x/build/autocertcache"
 	"golang.org/x/crypto/acme/autocert"
 	"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{
 		TLSConfig: &tls.Config{
-			GetCertificate: m.GetCertificate,
+			GetCertificate: autocertManager.GetCertificate,
 		},
 	}
 	http2.ConfigureServer(srv, &http2.Server{
@@ -468,9 +461,21 @@ func (ln tcpKeepAliveListener) Accept() (c net.Conn, err 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)
-	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
 }
 

+ 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.")
 	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.")
+	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 {
@@ -147,11 +148,14 @@ func (app *h2i) Main() error {
 		InsecureSkipVerify: *flagInsecure,
 	}
 
-	hostAndPort := withPort(app.host)
+	hostAndPort := *flagDial
+	if hostAndPort == "" {
+		hostAndPort = withPort(app.host)
+	}
 	log.Printf("Connecting to %s ...", hostAndPort)
 	tc, err := tls.Dial("tcp", hostAndPort, cfg)
 	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())
 	defer tc.Close()
@@ -460,6 +464,15 @@ func (app *h2i) readFrames() error {
 				app.hdec = hpack.NewDecoder(tableSize, app.onNewHeaderField)
 			}
 			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"
-// 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
 // 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
-// permits a body. See RFC 2616, section 4.4.
+// permits a body. See RFC 7230, section 3.3.
 func bodyAllowedForStatus(status int) bool {
 	switch {
 	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
 // 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.
 //
 // For now this is only used a quick check for deciding when to clean
 // up Opaque URLs before sending requests from the Transport.
 // See golang.org/issue/16847
+//
+// 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 {
-	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 go18httpNoBody() io.ReadCloser { return nil } // for tests only

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

@@ -46,6 +46,7 @@ import (
 	"sync"
 	"time"
 
+	"golang.org/x/net/http/httpguts"
 	"golang.org/x/net/http2/hpack"
 )
 
@@ -220,12 +221,15 @@ func ConfigureServer(s *http.Server, conf *Server) error {
 	} else if s.TLSConfig.CipherSuites != nil {
 		// If they already provided a CipherSuite list, return
 		// an error if it has a bad order or is missing
-		// ECDHE_RSA_WITH_AES_128_GCM_SHA256.
-		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
 		sawBad := false
 		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
 			}
 			if isBadCipher(cs) {
@@ -235,7 +239,7 @@ func ConfigureServer(s *http.Server, conf *Server) error {
 			}
 		}
 		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.
 			//
 			// 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.
 			//
 			// So for now, do nothing here again.
@@ -649,7 +653,7 @@ func (sc *serverConn) condlogf(err error, format string, args ...interface{}) {
 	if err == nil {
 		return
 	}
-	if err == io.EOF || err == io.ErrUnexpectedEOF || isClosedConnError(err) {
+	if err == io.EOF || err == io.ErrUnexpectedEOF || isClosedConnError(err) || err == errPrefaceTimeout {
 		// Boring, expected errors.
 		sc.vlogf(format, args...)
 	} 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 {
 	errc := make(chan error, 1)
 	go func() {
@@ -908,7 +920,7 @@ func (sc *serverConn) readPreface() error {
 	defer timer.Stop()
 	select {
 	case <-timer.C:
-		return errors.New("timeout waiting for client preface")
+		return errPrefaceTimeout
 	case err := <-errc:
 		if err == nil {
 			if VerboseLogs {
@@ -1218,30 +1230,31 @@ func (sc *serverConn) startGracefulShutdown() {
 	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() {
-	sc.goAwayIn(ErrCodeNo, 0)
+	sc.goAway(ErrCodeNo)
 }
 
 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()
 	if sc.inGoAway {
 		return
 	}
-	if forceCloseIn != 0 {
-		sc.shutDownIn(forceCloseIn)
-	}
 	sc.inGoAway = true
 	sc.needToSendGoAway = true
 	sc.goAwayCode = code
@@ -1805,7 +1818,7 @@ func (st *stream) processTrailerHeaders(f *MetaHeadersFrame) error {
 	if st.trailer != nil {
 		for _, hf := range f.RegularFields() {
 			key := sc.canonicalHeader(hf.Name)
-			if !ValidTrailerHeader(key) {
+			if !httpguts.ValidTrailerHeader(key) {
 				// TODO: send more details to the peer somehow. But http2 has
 				// no way to send debug data at a stream level. Discuss with
 				// HTTP folk.
@@ -2252,6 +2265,7 @@ type responseWriterState struct {
 	wroteHeader   bool        // WriteHeader called (explicitly or implicitly). Not necessarily sent to user yet.
 	sentHeader    bool        // have we sent the header frame?
 	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
 	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.
 func (rws *responseWriterState) declareTrailer(k string) {
 	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)
 		return
 	}
@@ -2309,8 +2323,16 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
 			clen = strconv.Itoa(len(p))
 		}
 		_, 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
 		if _, ok := rws.snapHeader["Date"]; !ok {
@@ -2333,6 +2355,7 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
 			date:          date,
 		})
 		if err != nil {
+			rws.dirty = true
 			return 0, err
 		}
 		if endStream {
@@ -2354,6 +2377,7 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
 	if len(p) > 0 || endStream {
 		// only send a 0 byte DATA frame if we're ending the stream.
 		if err := rws.conn.writeDataFromHandler(rws.stream, p, endStream); err != nil {
+			rws.dirty = true
 			return 0, err
 		}
 	}
@@ -2365,6 +2389,9 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
 			trailers:  rws.trailers,
 			endStream: true,
 		})
+		if err != nil {
+			rws.dirty = true
+		}
 		return len(p), err
 	}
 	return len(p), nil
@@ -2388,7 +2415,7 @@ const TrailerPrefix = "Trailer:"
 // after the header has already been flushed. Because the Go
 // ResponseWriter interface has no way to set Trailers (only the
 // 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
 // header, the official ResponseWriter rules said trailers in Go must
 // be predeclared, and then we reuse the same ResponseWriter.Header()
@@ -2472,6 +2499,24 @@ func (w *responseWriter) Header() http.Header {
 	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) {
 	rws := w.rws
 	if rws == nil {
@@ -2482,6 +2527,7 @@ func (w *responseWriter) WriteHeader(code int) {
 
 func (rws *responseWriterState) writeHeader(code int) {
 	if !rws.wroteHeader {
+		checkWriteHeaderCode(code)
 		rws.wroteHeader = true
 		rws.status = code
 		if len(rws.handlerHeader) > 0 {
@@ -2504,7 +2550,7 @@ func cloneHeader(h http.Header) http.Header {
 //
 // * Handler calls w.Write or w.WriteString ->
 // * -> rws.bw (*bufio.Writer) ->
-// * (Handler migth call Flush)
+// * (Handler might call Flush)
 // * -> chunkWriter{rws}
 // * -> responseWriterState.writeChunk(p []byte)
 // * -> 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() {
 	rws := w.rws
+	dirty := rws.dirty
 	rws.handlerDone = true
 	w.Flush()
 	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.
@@ -2744,7 +2799,7 @@ func (sc *serverConn) startPush(msg *startPushRequest) {
 }
 
 // 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)) {
 	v = textproto.TrimString(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
 // disabled. See comments on h1ServerShutdownChan above for why
 // 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() {
 	testHookOnPanicMu = new(sync.Mutex)
+	goAwayTimeout = 25 * time.Millisecond
 }
 
 func resetHooks() {
@@ -286,7 +287,7 @@ func (st *serverTester) greetAndCheckSettings(checkSetting func(s Setting) error
 
 		case *WindowUpdateFrame:
 			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)
 			if f.Increment != incr {
@@ -1717,7 +1718,6 @@ func TestServer_Response_NoData_Header_FooBar(t *testing.T) {
 		wanth := [][2]string{
 			{":status", "200"},
 			{"foo-bar", "some-value"},
-			{"content-type", "text/plain; charset=utf-8"},
 			{"content-length", "0"},
 		}
 		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) {
 	const msg = "hi"
 	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:Range", "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
 	}, func(st *serverTester) {
 		getSlash(st)
@@ -2952,7 +2988,6 @@ func TestServerDoesntWriteInvalidHeaders(t *testing.T) {
 		wanth := [][2]string{
 			{":status", "200"},
 			{"ok1", "x"},
-			{"content-type", "text/plain; charset=utf-8"},
 			{"content-length", "0"},
 		}
 		if !reflect.DeepEqual(goth, wanth) {
@@ -2972,7 +3007,7 @@ func BenchmarkServerGets(b *testing.B) {
 	defer st.Close()
 	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 {
 		b.Fatal(err)
 	}
@@ -3010,7 +3045,7 @@ func BenchmarkServerPosts(b *testing.B) {
 	defer st.Close()
 	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 {
 		b.Fatal(err)
 	}
@@ -3188,12 +3223,18 @@ func TestConfigureServer(t *testing.T) {
 				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",
 			tlsConfig: &tls.Config{
 				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",
@@ -3259,7 +3300,6 @@ func TestServerNoAutoContentLengthOnHead(t *testing.T) {
 	headers := st.decodeHeader(h.HeaderBlockFragment())
 	want := [][2]string{
 		{":status", "200"},
-		{"content-type", "text/plain; charset=utf-8"},
 	}
 	if !reflect.DeepEqual(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()
 
 	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 {
 		b.Fatal(err)
 	}
@@ -3343,7 +3383,7 @@ func BenchmarkServer_PostRequest(b *testing.B) {
 	})
 	defer st.Close()
 	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 {
 		b.Fatal(err)
 	}
@@ -3685,3 +3725,37 @@ func TestRequestBodyReadCloseRace(t *testing.T) {
 		<-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"
 	"log"
 	"math"
+	mathrand "math/rand"
 	"net"
 	"net/http"
 	"sort"
@@ -86,7 +87,7 @@ type Transport struct {
 
 	// MaxHeaderListSize is the http2 SETTINGS_MAX_HEADER_LIST_SIZE to
 	// 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
 	// want to advertise an ulimited value to the peer, Transport
 	// 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
 	streams         map[uint32]*clientStream // client-initiated
 	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
 	bw              *bufio.Writer
 	br              *bufio.Reader
 	fr              *Framer
 	lastActive      time.Time
 	// 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
 	henc    *hpack.Encoder
@@ -216,35 +219,45 @@ type clientStream struct {
 	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)
 	if req.Cancel == nil && ctx.Done() == nil {
-		return
+		return nil
 	}
 	select {
 	case <-req.Cancel:
-		cs.cancelStream()
-		cs.bufPipe.CloseWithError(errRequestCanceled)
+		return errRequestCanceled
 	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.bufPipe.CloseWithError(ctx.Err())
-	case <-cs.done:
+		cs.bufPipe.CloseWithError(err)
 	}
 }
 
 func (cs *clientStream) cancelStream() {
-	cs.cc.mu.Lock()
+	cc := cs.cc
+	cc.mu.Lock()
 	didReset := cs.didReset
 	cs.didReset = true
-	cs.cc.mu.Unlock()
+	cc.mu.Unlock()
 
 	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) {
 	if err == nil {
 		panic("nil error")
@@ -286,7 +306,26 @@ func (sew stickyErrWriter) Write(p []byte) (n int, err error) {
 	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.
 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)
-	for {
+	for retry := 0; ; retry++ {
 		cc, err := t.connPool().GetClientConn(req, addr)
 		if err != nil {
 			t.vlogf("http2: Transport failed to get client conn for %s: %v", addr, err)
 			return nil, err
 		}
 		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 {
@@ -360,43 +410,50 @@ func (t *Transport) CloseIdleConnections() {
 }
 
 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
 // response headers. It is always called with a non-nil error.
 // It returns either a request to retry (either the same request, or a
 // modified clone), or an error if the request can't be replayed.
-func 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
-	case errClientConnUnusable, errClientConnGotGoAway:
+	}
+	if !afterBodyWrite {
 		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) {
@@ -474,17 +531,18 @@ func (t *Transport) NewClientConn(c net.Conn) (*ClientConn, error) {
 
 func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, error) {
 	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 {
 		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 {
 	cc.mu.Lock()
 	defer cc.mu.Unlock()
@@ -571,8 +631,7 @@ func (cc *ClientConn) canTakeNewRequestLocked() bool {
 		return false
 	}
 	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
@@ -694,7 +753,7 @@ func checkConnHeaders(req *http.Request) error {
 // req.ContentLength, where 0 actually means zero (not unknown) and -1
 // means unknown.
 func actualContentLength(req *http.Request) int64 {
-	if req.Body == nil {
+	if req.Body == nil || reqBodyIsNoBody(req.Body) {
 		return 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) {
+	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 {
-		return nil, err
+		return nil, false, err
 	}
 	if cc.idleTimer != nil {
 		cc.idleTimer.Stop()
@@ -713,20 +777,19 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
 
 	trailers, err := commaSeparatedTrailers(req)
 	if err != nil {
-		return nil, err
+		return nil, false, err
 	}
 	hasTrailers := trailers != ""
 
 	cc.mu.Lock()
-	cc.lastActive = time.Now()
-	if cc.closed || !cc.canTakeNewRequestLocked() {
+	if err := cc.awaitOpenSlotForRequest(req); err != nil {
 		cc.mu.Unlock()
-		return nil, errClientConnUnusable
+		return nil, false, err
 	}
 
 	body := req.Body
-	hasBody := body != nil
 	contentLen := actualContentLength(req)
+	hasBody := contentLen != 0
 
 	// TODO(bradfitz): this is a copy of the logic in net/http. Unify somewhere?
 	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)
 	if err != nil {
 		cc.mu.Unlock()
-		return nil, err
+		return nil, false, err
 	}
 
 	cs := cc.newStream()
@@ -767,7 +830,7 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
 
 	cc.wmu.Lock()
 	endStream := !hasBody && !hasTrailers
-	werr := cc.writeHeaders(cs.ID, endStream, hdrs)
+	werr := cc.writeHeaders(cs.ID, endStream, int(cc.maxFrameSize), hdrs)
 	cc.wmu.Unlock()
 	traceWroteHeaders(cs.trace)
 	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;
 		// no need to keep writing)
 		traceWroteRequest(cs.trace, werr)
-		return nil, werr
+		return nil, false, werr
 	}
 
 	var respHeaderTimer <-chan time.Time
@@ -800,7 +863,7 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
 	bodyWritten := false
 	ctx := reqContext(req)
 
-	handleReadLoopResponse := func(re resAndError) (*http.Response, error) {
+	handleReadLoopResponse := func(re resAndError) (*http.Response, bool, error) {
 		res := re.res
 		if re.err != nil || res.StatusCode > 299 {
 			// 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)
 		}
 		if re.err != nil {
-			if re.err == errClientConnGotGoAway {
-				cc.mu.Lock()
-				if cs.startedWrite {
-					re.err = errClientConnGotGoAwayAfterSomeReqBody
-				}
-				cc.mu.Unlock()
-			}
 			cc.forgetStreamID(cs.ID)
-			return nil, re.err
+			return nil, cs.getStartedWrite(), re.err
 		}
 		res.Request = req
 		res.TLS = cc.tlsState
-		return res, nil
+		return res, false, nil
 	}
 
 	for {
@@ -836,37 +892,37 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
 		case re := <-readLoopResCh:
 			return handleReadLoopResponse(re)
 		case <-respHeaderTimer:
-			cc.forgetStreamID(cs.ID)
 			if !hasBody || bodyWritten {
 				cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
 			} else {
 				bodyWriter.cancel()
 				cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel)
 			}
-			return nil, errTimeout
-		case <-ctx.Done():
 			cc.forgetStreamID(cs.ID)
+			return nil, cs.getStartedWrite(), errTimeout
+		case <-ctx.Done():
 			if !hasBody || bodyWritten {
 				cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
 			} else {
 				bodyWriter.cancel()
 				cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel)
 			}
-			return nil, ctx.Err()
-		case <-req.Cancel:
 			cc.forgetStreamID(cs.ID)
+			return nil, cs.getStartedWrite(), ctx.Err()
+		case <-req.Cancel:
 			if !hasBody || bodyWritten {
 				cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
 			} else {
 				bodyWriter.cancel()
 				cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel)
 			}
-			return nil, errRequestCanceled
+			cc.forgetStreamID(cs.ID)
+			return nil, cs.getStartedWrite(), errRequestCanceled
 		case <-cs.peerReset:
 			// processResetStream already removed the
 			// stream from the streams map; no need for
 			// forgetStreamID.
-			return nil, cs.resetErr
+			return nil, cs.getStartedWrite(), cs.resetErr
 		case err := <-bodyWriter.resc:
 			// Prefer the read loop's response, if available. Issue 16102.
 			select {
@@ -875,7 +931,7 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
 			default:
 			}
 			if err != nil {
-				return nil, err
+				return nil, cs.getStartedWrite(), err
 			}
 			bodyWritten = true
 			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
-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)
-	frameSize := int(cc.maxFrameSize)
 	for len(hdrs) > 0 && cc.werr == nil {
 		chunk := hdrs
-		if len(chunk) > frameSize {
-			chunk = chunk[:frameSize]
+		if len(chunk) > maxFrameSize {
+			chunk = chunk[:maxFrameSize]
 		}
 		hdrs = hdrs[len(chunk):]
 		endHeaders := len(hdrs) == 0
@@ -1002,17 +1099,26 @@ func (cs *clientStream) writeRequestBody(body io.Reader, bodyCloser io.Closer) (
 	var trls []byte
 	if hasTrailers {
 		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()
 	defer cc.wmu.Unlock()
 
 	// Two ways to send END_STREAM: either with trailers, or
 	// with an empty DATA frame.
 	if len(trls) > 0 {
-		err = cc.writeHeaders(cs.ID, true, trls)
+		err = cc.writeHeaders(cs.ID, true, maxFrameSize, trls)
 	} else {
 		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
-			}
-			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
+			} 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
 }
 
@@ -1188,17 +1318,29 @@ func shouldSendReqContentLength(method string, contentLength int64) bool {
 }
 
 // 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()
+
+	hlSize := uint64(0)
 	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
 		lowKey := strings.ToLower(k)
 		for _, v := range vv {
 			cc.writeHeader(lowKey, v)
 		}
 	}
-	return cc.hbuf.Bytes()
+	return cc.hbuf.Bytes(), nil
 }
 
 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)
 		}
 		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
 }
@@ -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.
 type clientConnReadLoop struct {
 	cc            *ClientConn
-	activeRes     map[uint32]*clientStream // keyed by streamID
 	closeWhenIdle bool
 }
 
 // readLoop runs in its own goroutine and reads and dispatches frames.
 func (cc *ClientConn) readLoop() {
-	rl := &clientConnReadLoop{
-		cc:        cc,
-		activeRes: make(map[uint32]*clientStream),
-	}
-
+	rl := &clientConnReadLoop{cc: cc}
 	defer rl.cleanup()
 	cc.readerErr = rl.run()
 	if ce, ok := cc.readerErr.(ConnectionError); ok {
@@ -1319,10 +1458,8 @@ func (rl *clientConnReadLoop) cleanup() {
 	} else if err == io.EOF {
 		err = io.ErrUnexpectedEOF
 	}
-	for _, cs := range rl.activeRes {
-		cs.bufPipe.CloseWithError(err)
-	}
 	for _, cs := range cc.streams {
+		cs.bufPipe.CloseWithError(err) // no-op if already closed
 		select {
 		case cs.resc <- resAndError{err: err}:
 		default:
@@ -1345,8 +1482,9 @@ func (rl *clientConnReadLoop) run() error {
 			cc.vlogf("http2: Transport readFrame error on conn %p: (%T) %v", cc, err, err)
 		}
 		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.forgetStreamID(cs.ID)
 				if se.Cause == nil {
 					se.Cause = cc.fr.errDetail
 				}
@@ -1399,7 +1537,7 @@ func (rl *clientConnReadLoop) run() error {
 			}
 			return err
 		}
-		if rl.closeWhenIdle && gotReply && maybeIdle && len(rl.activeRes) == 0 {
+		if rl.closeWhenIdle && gotReply && maybeIdle {
 			cc.closeIfIdle()
 		}
 	}
@@ -1407,13 +1545,31 @@ func (rl *clientConnReadLoop) run() error {
 
 func (rl *clientConnReadLoop) processHeaders(f *MetaHeadersFrame) error {
 	cc := rl.cc
-	cs := cc.streamByID(f.StreamID, f.StreamEnded())
+	cs := cc.streamByID(f.StreamID, false)
 	if cs == nil {
 		// We'd get here if we canceled a request while the
 		// server had its response still in flight. So if this
 		// was just something we canceled, ignore it.
 		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.trace != nil {
 			// 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.
 		cs.cc.writeStreamReset(f.StreamID, ErrCodeProtocol, err)
+		cc.forgetStreamID(cs.ID)
 		cs.resc <- resAndError{err: err}
 		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.
 		return nil
 	}
-	if res.Body != noBody {
-		rl.activeRes[cs.ID] = cs
-	}
 	cs.resTrailer = &res.Trailer
 	cs.resc <- resAndError{res: res}
 	return nil
@@ -1466,11 +1620,11 @@ func (rl *clientConnReadLoop) handleResponse(cs *clientStream, f *MetaHeadersFra
 
 	status := f.PseudoValue("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)
 	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 {
@@ -1668,6 +1822,7 @@ func (b transportResponseBody) Close() error {
 	}
 
 	cs.bufPipe.BreakWithError(errClosedResponseBody)
+	cc.forgetStreamID(cs.ID)
 	return nil
 }
 
@@ -1702,7 +1857,23 @@ func (rl *clientConnReadLoop) processData(f *DataFrame) error {
 		}
 		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 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.
 		cc.mu.Lock()
 		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
 		// 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.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.wmu.Unlock()
 		}
-		didReset := cs.didReset
 		cc.mu.Unlock()
 
 		if len(data) > 0 && !didReset {
@@ -1753,11 +1935,10 @@ func (rl *clientConnReadLoop) endStreamError(cs *clientStream, err error) {
 		err = io.EOF
 		code = cs.copyTrailers
 	}
-	cs.bufPipe.closeWithErrorAndCode(err, code)
-	delete(rl.activeRes, cs.ID)
 	if isConnectionCloseRequest(cs.req) {
 		rl.closeWhenIdle = true
 	}
+	cs.bufPipe.closeWithErrorAndCode(err, code)
 
 	select {
 	case cs.resc <- resAndError{err: err}:
@@ -1805,6 +1986,8 @@ func (rl *clientConnReadLoop) processSettings(f *SettingsFrame) error {
 			cc.maxFrameSize = s.Val
 		case SettingMaxConcurrentStreams:
 			cc.maxConcurrentStreams = s.Val
+		case SettingMaxHeaderListSize:
+			cc.peerMaxHeaderListSize = uint64(s.Val)
 		case SettingInitialWindowSize:
 			// Values above the maximum flow-control
 			// 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.cc.cond.Broadcast() // wake up checkResetOrDone via clientStream.awaitFlowControl
 	}
-	delete(rl.activeRes, cs.ID)
 	return nil
 }
 
@@ -1971,6 +2153,7 @@ func (cc *ClientConn) writeStreamReset(streamID uint32, code ErrCode, err error)
 
 var (
 	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")
 )
 

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

@@ -13,9 +13,11 @@ import (
 	"fmt"
 	"io"
 	"io/ioutil"
+	"log"
 	"math/rand"
 	"net"
 	"net/http"
+	"net/http/httptest"
 	"net/url"
 	"os"
 	"reflect"
@@ -417,6 +419,11 @@ func TestActualContentLength(t *testing.T) {
 			req:  &http.Request{Body: panicReader{}, ContentLength: 5},
 			want: 5,
 		},
+		// http.NoBody means 0, not -1.
+		3: {
+			req:  &http.Request{Body: go18httpNoBody()},
+			want: 0,
+		},
 	}
 	for i, tt := range tests {
 		got := actualContentLength(tt.req)
@@ -680,7 +687,7 @@ func newLocalListener(t *testing.T) net.Listener {
 	return ln
 }
 
-func (ct *clientTester) greet() {
+func (ct *clientTester) greet(settings ...Setting) {
 	buf := make([]byte, len(ClientPreface))
 	_, err := io.ReadFull(ct.sc, buf)
 	if err != nil {
@@ -694,7 +701,7 @@ func (ct *clientTester) greet() {
 		ct.t.Fatalf("Wanted client settings frame; got %v", f)
 		_ = sf // stash it away?
 	}
-	if err := ct.fr.WriteSettings(); err != nil {
+	if err := ct.fr.WriteSettings(settings...); err != nil {
 		ct.t.Fatal(err)
 	}
 	if err := ct.fr.WriteSettingsAck(); err != nil {
@@ -1365,6 +1372,269 @@ func testInvalidTrailer(t *testing.T, trailers headerType, wantErr error, writeT
 	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) {
 	ct := newClientTester(t)
 	ct.client = func() error {
@@ -1423,7 +1693,7 @@ func TestTransportChecksResponseHeaderListSize(t *testing.T) {
 	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
 // a stream error, but others like cancel should be similar)
 func TestTransportBodyReadErrorType(t *testing.T) {
@@ -2021,6 +2291,65 @@ func TestTransportReadHeadResponse(t *testing.T) {
 	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
 
 func (b neverEnding) Read(p []byte) (int, error) {
@@ -2205,12 +2534,11 @@ func testTransportUsesGoAwayDebugError(t *testing.T, failMidBody bool) {
 	ct.run()
 }
 
-// See golang.org/issue/16481
-func TestTransportReturnsUnusedFlowControl(t *testing.T) {
+func testTransportReturnsUnusedFlowControl(t *testing.T, oneDataFrame bool) {
 	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 {
 		req, _ := http.NewRequest("GET", "https://dummy.tld/", nil)
@@ -2218,13 +2546,13 @@ func TestTransportReturnsUnusedFlowControl(t *testing.T) {
 		if err != nil {
 			return err
 		}
-		<-serverWroteBody
+		<-serverWroteFirstByte
 
 		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)
 		}
 		res.Body.Close() // leaving 4999 bytes unread
-		clientClosed <- true
+		close(clientClosed)
 
 		return nil
 	}
@@ -2259,10 +2587,27 @@ func TestTransportReturnsUnusedFlowControl(t *testing.T) {
 			EndStream:     false,
 			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"
 		for {
@@ -2276,7 +2621,7 @@ func TestTransportReturnsUnusedFlowControl(t *testing.T) {
 			switch waitingFor {
 			case "RSTStreamFrame":
 				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"
 			case "WindowUpdateFrame":
@@ -2290,6 +2635,16 @@ func TestTransportReturnsUnusedFlowControl(t *testing.T) {
 	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
 // receives SETTINGS with INITIAL_WINDOW_SIZE from server.
 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) {
 	type result struct {
 		path string
@@ -2549,9 +2904,9 @@ func TestTransportRequestPathPseudo(t *testing.T) {
 			},
 			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: {
 			req: &http.Request{
 				Method: "GET",
@@ -2560,7 +2915,7 @@ func TestTransportRequestPathPseudo(t *testing.T) {
 					Path: "//foo",
 				},
 			},
-			want: result{err: `invalid request :path "//foo"`},
+			want: result{path: "//foo"},
 		},
 
 		// Opaque with //$Matching_Hostname/path
@@ -2631,7 +2986,7 @@ func TestTransportRequestPathPseudo(t *testing.T) {
 		},
 	}
 	for i, tt := range tests {
-		cc := &ClientConn{}
+		cc := &ClientConn{peerMaxHeaderListSize: 0xffffffffffffffff}
 		cc.henc = hpack.NewEncoder(&cc.hbuf)
 		cc.mu.Lock()
 		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) {
 	var dialer struct {
 		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) {
 	tests := []struct {
 		scheme, authority string
@@ -2969,3 +3690,158 @@ func TestTransportAllocationsAfterResponseBodyClose(t *testing.T) {
 		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"
 	"net/http"
 	"net/url"
-	"time"
 
 	"golang.org/x/net/http2/hpack"
 	"golang.org/x/net/lex/httplex"
@@ -90,11 +89,7 @@ type writeGoAway struct {
 
 func (p *writeGoAway) writeFrame(ctx writeContext) error {
 	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
 }
 

+ 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 {
 		return 0
 	}
-	l, _ := multipartMessageBodyDataLen(proto, p.Data, p.Extensions)
+	l, _ := multipartMessageBodyDataLen(proto, true, p.Data, p.Extensions)
 	return 4 + l
 }
 
 // Marshal implements the Marshal method of MessageBody interface.
 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
 // body.
-func parseDstUnreach(proto int, b []byte) (MessageBody, error) {
+func parseDstUnreach(proto int, typ Type, b []byte) (MessageBody, error) {
 	if len(b) < 4 {
 		return nil, errMessageTooShort
 	}
 	p := &DstUnreach{}
 	var err error
-	p.Data, p.Extensions, err = parseMultipartMessageBody(proto, b)
+	p.Data, p.Extensions, err = parseMultipartMessageBody(proto, typ, b)
 	if err != nil {
 		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.
-func parseEcho(proto int, b []byte) (MessageBody, error) {
+func parseEcho(proto int, _ Type, b []byte) (MessageBody, error) {
 	bodyLen := len(b)
 	if bodyLen < 4 {
 		return nil, errMessageTooShort
@@ -43,3 +43,115 @@ func parseEcho(proto int, b []byte) (MessageBody, error) {
 	}
 	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
 
-import "encoding/binary"
+import (
+	"encoding/binary"
+
+	"golang.org/x/net/ipv4"
+	"golang.org/x/net/ipv6"
+)
 
 // An Extension represents an ICMP extension.
 type Extension interface {
@@ -38,7 +43,7 @@ func validExtensionHeader(b []byte) bool {
 // It will return a list of ICMP extensions and an adjusted length
 // attribute that represents the length of the padded original
 // 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
 	// out there. Set the length attribute l to 128 when it looks
 	// inappropriate for backwards compatibility.
@@ -48,20 +53,28 @@ func parseExtensions(b []byte, l int) ([]Extension, int, error) {
 	// header.
 	//
 	// 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
 		}
-		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
 		}
+		if !validExtensionHeader(b[l:]) {
+			if l == 128 {
+				return nil, -1, errNoExtension
+			}
+			l = 128
+			if !validExtensionHeader(b[l:]) {
+				return nil, -1, errNoExtension
+			}
+		}
 	}
 	var exts []Extension
 	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
 			}
 			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:]
 	}

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

@@ -5,253 +5,327 @@
 package icmp
 
 import (
+	"fmt"
 	"net"
 	"reflect"
 	"testing"
 
 	"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) {
 	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 {
 			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 (
 	classInterfaceInfo = 2
-
-	afiIPv4 = 1
-	afiIPv6 = 2
 )
 
 const (
@@ -127,11 +124,11 @@ func (ifi *InterfaceInfo) parseIfIndex(b []byte) ([]byte, error) {
 func (ifi *InterfaceInfo) marshalIPAddr(proto int, b []byte) []byte {
 	switch proto {
 	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())
 		b = b[4+net.IPv4len:]
 	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())
 		b = b[4+net.IPv6len:]
 	}
@@ -145,14 +142,14 @@ func (ifi *InterfaceInfo) parseIPAddr(b []byte) ([]byte, error) {
 	afi := int(binary.BigEndian.Uint16(b[:2]))
 	b = b[4:]
 	switch afi {
-	case afiIPv4:
+	case iana.AddrFamilyIPv4:
 		if len(b) < net.IPv4len {
 			return nil, errMessageTooShort
 		}
 		ifi.Addr.IP = make(net.IP, net.IPv4len)
 		copy(ifi.Addr.IP, b[:net.IPv4len])
 		b = b[net.IPv4len:]
-	case afiIPv6:
+	case iana.AddrFamilyIPv6:
 		if len(b) < net.IPv6len {
 			return nil, errMessageTooShort
 		}
@@ -234,3 +231,92 @@ func parseInterfaceInfo(b []byte) (Extension, error) {
 	}
 	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"
 	"runtime"
 
+	"golang.org/x/net/internal/socket"
 	"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
 // invoking packet, which is contained in ICMP error message.
 func ParseIPv4Header(b []byte) (*ipv4.Header, error) {
@@ -36,12 +41,12 @@ func ParseIPv4Header(b []byte) (*ipv4.Header, error) {
 	}
 	switch runtime.GOOS {
 	case "darwin":
-		h.TotalLen = int(nativeEndian.Uint16(b[2:4]))
+		h.TotalLen = int(socket.NativeEndian.Uint16(b[2:4]))
 	case "freebsd":
 		if freebsdVersion >= 1000000 {
 			h.TotalLen = int(binary.BigEndian.Uint16(b[2:4]))
 		} else {
-			h.TotalLen = int(nativeEndian.Uint16(b[2:4]))
+			h.TotalLen = int(socket.NativeEndian.Uint16(b[2:4]))
 		}
 	default:
 		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"
 	"testing"
 
+	"golang.org/x/net/internal/socket"
 	"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) {
-	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 interface and next-hop identification are
 // defined in RFC 5837.
+// PROBE: A utility for probing interfaces is defined in RFC 8335.
 package icmp // import "golang.org/x/net/icmp"
 
 import (
@@ -107,21 +108,25 @@ func (m *Message) Marshal(psh []byte) ([]byte, error) {
 	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.ICMPTypeTimeExceeded:           parseTimeExceeded,
 	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.ICMPTypePacketTooBig:           parsePacketTooBig,
 	ipv6.ICMPTypeTimeExceeded:           parseTimeExceeded,
 	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.
@@ -143,7 +148,7 @@ func ParseMessage(proto int, b []byte) (*Message, error) {
 	if fn, ok := parseFns[m.Type]; !ok {
 		m.Body, err = parseDefaultMessageBody(proto, b[4:])
 	} else {
-		m.Body, err = fn(proto, b[4:])
+		m.Body, err = fn(proto, m.Type, b[4:])
 	}
 	if err != nil {
 		return nil, err

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

@@ -15,120 +15,141 @@ import (
 	"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
 // and a required length for a padded original datagram in wire
 // 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 {
 		bodyLen += ext.Len(proto)
 	}
 	if bodyLen > 0 {
-		dataLen = multipartMessageOrigDatagramLen(proto, b)
+		if withOrigDgram {
+			dataLen = multipartMessageOrigDatagramLen(proto, b)
+		}
 		bodyLen += 4 // length of extension header
 	} else {
 		dataLen = len(b)
@@ -50,8 +52,8 @@ func multipartMessageOrigDatagramLen(proto int, b []byte) int {
 // marshalMultipartMessageBody takes data as an original datagram and
 // exts as extesnsions, and returns a binary encoding of message body.
 // 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)
 	copy(b[4:], data)
 	off := dataLen + 4
@@ -71,16 +73,23 @@ func marshalMultipartMessageBody(proto int, data []byte, exts []Extension) ([]by
 					return nil, err
 				}
 				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:])
 		b[dataLen+4+2] ^= byte(s)
 		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
@@ -88,7 +97,7 @@ func marshalMultipartMessageBody(proto int, data []byte, exts []Extension) ([]by
 
 // parseMultipartMessageBody parses b as either a non-multipart
 // 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
 	switch proto {
 	case iana.ProtocolICMP:
@@ -99,11 +108,14 @@ func parseMultipartMessageBody(proto int, b []byte) ([]byte, []Extension, error)
 	if len(b) == 4 {
 		return nil, nil, nil
 	}
-	exts, l, err := parseExtensions(b[4:], l)
+	exts, l, err := parseExtensions(typ, b[4:], l)
 	if err != nil {
 		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
 }

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

@@ -5,6 +5,7 @@
 package icmp_test
 
 import (
+	"errors"
 	"fmt"
 	"net"
 	"reflect"
@@ -16,425 +17,557 @@ import (
 	"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 {
-			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 {
-			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 {
+		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:
-			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) {
-				t.Error(dumpExtensions(i, got.Extensions, want.Extensions))
+				return errors.New(dumpExtensions(got.Extensions, want.Extensions))
 			}
 			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:
-			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) {
-				t.Error(dumpExtensions(i, got.Extensions, want.Extensions))
+				return errors.New(dumpExtensions(got.Extensions, want.Extensions))
 			}
 			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:
-			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) {
-				t.Error(dumpExtensions(i, got.Extensions, want.Extensions))
+				return errors.New(dumpExtensions(got.Extensions, want.Extensions))
 			}
 			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
-	for j, got := range gotExts {
+	for i, got := range gotExts {
 		switch got := got.(type) {
 		case *icmp.MPLSLabelStack:
-			want := wantExts[j].(*icmp.MPLSLabelStack)
+			want := wantExts[i].(*icmp.MPLSLabelStack)
 			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:
-			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) {
-				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]
 }
 
-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 {
 			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.
-func parsePacketTooBig(proto int, b []byte) (MessageBody, error) {
+func parsePacketTooBig(proto int, _ Type, b []byte) (MessageBody, error) {
 	bodyLen := len(b)
 	if bodyLen < 4 {
 		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 {
 		return 0
 	}
-	l, _ := multipartMessageBodyDataLen(proto, p.Data, p.Extensions)
+	l, _ := multipartMessageBodyDataLen(proto, true, p.Data, p.Extensions)
 	return 4 + l
 }
 
@@ -33,7 +33,7 @@ func (p *ParamProb) Marshal(proto int) ([]byte, error) {
 		copy(b[4:], p.Data)
 		return b, nil
 	}
-	b, err := marshalMultipartMessageBody(proto, p.Data, p.Extensions)
+	b, err := marshalMultipartMessageBody(proto, true, p.Data, p.Extensions)
 	if err != nil {
 		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.
-func parseParamProb(proto int, b []byte) (MessageBody, error) {
+func parseParamProb(proto int, typ Type, b []byte) (MessageBody, error) {
 	if len(b) < 4 {
 		return nil, errMessageTooShort
 	}
@@ -55,7 +55,7 @@ func parseParamProb(proto int, b []byte) (MessageBody, error) {
 	}
 	p.Pointer = uintptr(b[0])
 	var err error
-	p.Data, p.Extensions, err = parseMultipartMessageBody(proto, b)
+	p.Data, p.Extensions, err = parseMultipartMessageBody(proto, typ, b)
 	if err != nil {
 		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 {
 		return 0
 	}
-	l, _ := multipartMessageBodyDataLen(proto, p.Data, p.Extensions)
+	l, _ := multipartMessageBodyDataLen(proto, true, p.Data, p.Extensions)
 	return 4 + l
 }
 
 // Marshal implements the Marshal method of MessageBody interface.
 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.
-func parseTimeExceeded(proto int, b []byte) (MessageBody, error) {
+func parseTimeExceeded(proto int, typ Type, b []byte) (MessageBody, error) {
 	if len(b) < 4 {
 		return nil, errMessageTooShort
 	}
 	p := &TimeExceeded{}
 	var err error
-	p.Data, p.Extensions, err = parseMultipartMessageBody(proto, b)
+	p.Data, p.Extensions, err = parseMultipartMessageBody(proto, typ, b)
 	if err != nil {
 		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
 	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.
 	p = idna.New(
 		idna.MapForLookup(),
@@ -60,6 +64,7 @@ func ExampleNew() {
 
 	// Output:
 	// *.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>
 }

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

@@ -21,6 +21,7 @@ import (
 	"unicode/utf8"
 
 	"golang.org/x/text/secure/bidirule"
+	"golang.org/x/text/unicode/bidi"
 	"golang.org/x/text/unicode/norm"
 )
 
@@ -67,6 +68,15 @@ func VerifyDNSLength(verify bool) Option {
 	return func(o *options) { o.verifyDNSLength = verify }
 }
 
+// RemoveLeadingDots removes leading label separators. Leading runes that map to
+// dots, such as U+3002 IDEOGRAPHIC FULL STOP, are removed as well.
+//
+// This is the behavior suggested by the UTS #46 and is adopted by some
+// browsers.
+func RemoveLeadingDots(remove bool) Option {
+	return func(o *options) { o.removeLeadingDots = remove }
+}
+
 // ValidateLabels sets whether to check the mandatory label validation criteria
 // as defined in Section 5.4 of RFC 5891. This includes testing for correct use
 // of hyphens ('-'), normalization, validity of runes, and the context rules.
@@ -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
 // hyphen). This is set by default for MapForLookup and ValidateForRegistration.
 //
@@ -137,10 +147,11 @@ func MapForLookup() Option {
 }
 
 type options struct {
-	transitional    bool
-	useSTD3Rules    bool
-	validateLabels  bool
-	verifyDNSLength bool
+	transitional      bool
+	useSTD3Rules      bool
+	validateLabels    bool
+	verifyDNSLength   bool
+	removeLeadingDots bool
 
 	trie *idnaTrie
 
@@ -149,14 +160,14 @@ type options struct {
 
 	// mapping implements a validation and mapping step as defined in RFC 5895
 	// 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
 	// defined in RFC 5893.
 	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 {
 	options
 }
@@ -289,12 +300,16 @@ func (e runeError) Error() string {
 // see http://www.unicode.org/reports/tr46.
 func (p *Profile) process(s string, toASCII bool) (string, error) {
 	var err error
+	var isBidi bool
 	if p.mapping != nil {
-		s, err = p.mapping(p, s)
+		s, isBidi, err = p.mapping(p, s)
 	}
 	// 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
 	// UTS 46 conformance tests suggests we should always check this.
 	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.
 				continue
 			}
+			isBidi = isBidi || bidirule.DirectionString(u) != bidi.LeftToRight
 			labels.set(u)
 			if err == nil && p.validateLabels {
 				err = p.fromPuny(p, u)
@@ -334,6 +350,14 @@ func (p *Profile) process(s string, toASCII bool) (string, error) {
 			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 {
 		for labels.reset(); !labels.done(); labels.next() {
 			label := labels.label()
@@ -365,41 +389,77 @@ func (p *Profile) process(s string, toASCII bool) (string, error) {
 	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) {
-		return s, &labelError{s, "V1"}
+		return s, false, &labelError{s, "V1"}
 	}
-	var err error
 	for i := 0; i < len(s); {
 		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.
 		switch p.simplify(info(v).category()) {
 		// TODO: handle the NV8 defined in the Unicode idna data set to allow
 		// for strict conformance to IDNA2008.
 		case valid, deviation:
 		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 (
-		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); {
 		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
 		i += sz
 		// Copy bytes not copied so far.
@@ -408,7 +468,7 @@ func validateAndMap(p *Profile, s string) (string, error) {
 			continue
 		case disallowed:
 			if err == nil {
-				r, _ := utf8.DecodeRuneInString(s[i:])
+				r, _ := utf8.DecodeRuneInString(s[start:])
 				err = runeError(r)
 			}
 			continue
@@ -426,7 +486,9 @@ func validateAndMap(p *Profile, s string) (string, error) {
 	}
 	if k == 0 {
 		// No changes so far.
-		s = norm.NFC.String(s)
+		if combinedInfoBits&mayNeedNorm != 0 {
+			s = norm.NFC.String(s)
+		}
 	} else {
 		b = append(b, s[k:]...)
 		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.
 		s = string(b)
 	}
-	return s, err
+	return s, bidi, err
 }
 
 // A labelIter allows iterating over domain name labels.
@@ -530,8 +592,13 @@ func validateFromPunycode(p *Profile, s string) error {
 	if !norm.NFC.IsNormalString(s) {
 		return &labelError{s, "V1"}
 	}
+	// TODO: detect whether string may have to be normalized in the following
+	// loop.
 	for i := 0; i < len(s); {
 		v, sz := trie.lookupString(s[i:])
+		if sz == 0 {
+			return runeError(utf8.RuneError)
+		}
 		if c := p.simplify(info(v).category()); c != valid && c != deviation {
 			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
 // 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 p.verifyDNSLength {
 			return &labelError{s, "A4"}
 		}
 		return nil
 	}
-	if p.bidirule != nil && !p.bidirule(s) {
-		return &labelError{s, "B"}
-	}
 	if !p.validateLabels {
 		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
 // 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
 //     }
 //   } else {
-//       15..13 unused
-//           12 modifier (including virama)
-//           11 virama modifier
+//       15..14 unused
+//       13     mayNeedNorm
+//       12..11 attributes
 //       10..8  joining type
 //        7..3  category type
 //   }
@@ -49,15 +49,20 @@ const (
 	joinShift = 8
 	joinMask  = 0x07
 
-	viramaModifier = 0x0800
+	// Attributes
+	attributesMask = 0x1800
+	viramaModifier = 0x1800
 	modifier       = 0x1000
+	rtl            = 0x0800
+
+	mayNeedNorm = 0x2000
 )
 
 // A category corresponds to a category defined in the IDNA mapping table.
 type category uint16
 
 const (
-	unknown              category = 0 // not defined currently in unicode.
+	unknown              category = 0 // not currently defined in unicode.
 	mapped               category = 1
 	disallowedSTD3Mapped category = 2
 	deviation            category = 3
@@ -110,5 +115,5 @@ func (c info) isModifier() 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
-// 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 // import "golang.org/x/net/internal/iana"
@@ -38,7 +38,7 @@ const (
 	CongestionExperienced = 0x3 // CE (Congestion Experienced)
 )
 
-// Protocol Numbers, Updated: 2016-06-22
+// Protocol Numbers, Updated: 2017-10-13
 const (
 	ProtocolIP             = 0   // IPv4 encapsulation, pseudo protocol number
 	ProtocolHOPOPT         = 0   // IPv6 Hop-by-Hop Option
@@ -178,3 +178,50 @@ const (
 	ProtocolROHC           = 142 // Robust Header Compression
 	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
 }{
 	{
-		"http://www.iana.org/assignments/dscp-registry/dscp-registry.xml",
+		"https://www.iana.org/assignments/dscp-registry/dscp-registry.xml",
 		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,
 	},
 	{
-		"http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml",
+		"https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml",
 		parseProtocolNumbers,
 	},
+	{
+		"http://www.iana.org/assignments/address-family-numbers/address-family-numbers.xml",
+		parseAddrFamilyNumbers,
+	},
 }
 
 func main() {
 	var bb bytes.Buffer
 	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 // import "golang.org/x/net/internal/iana"`+"\n\n")
 	for _, r := range registries {
@@ -291,3 +295,93 @@ func (pn *protocolNumbers) escape() []canonProtocolRecord {
 	}
 	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
 // license that can be found in the LICENSE file.
 
-// +build nacl plan9
+// +build js,wasm nacl plan9
 
 package nettest
 

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

@@ -64,7 +64,7 @@ func TestableNetwork(network string) bool {
 	switch network {
 	case "unix", "unixgram":
 		switch runtime.GOOS {
-		case "android", "nacl", "plan9", "windows":
+		case "android", "js", "nacl", "plan9", "windows":
 			return false
 		}
 		if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
@@ -72,8 +72,13 @@ func TestableNetwork(network string) bool {
 		}
 	case "unixpacket":
 		switch runtime.GOOS {
-		case "android", "darwin", "freebsd", "nacl", "plan9", "windows":
+		case "android", "darwin", "freebsd", "js", "nacl", "plan9", "windows":
 			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

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

@@ -10,6 +10,10 @@ package socket
 import "unsafe"
 
 func (v *iovec) set(b []byte) {
+	l := len(b)
+	if l == 0 {
+		return
+	}
 	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"
 
 func (v *iovec) set(b []byte) {
+	l := len(b)
+	if l == 0 {
+		return
+	}
 	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"
 
 func (v *iovec) set(b []byte) {
+	l := len(b)
+	if l == 0 {
+		return
+	}
 	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
 
 func (h *msghdr) setIov(vs []iovec) {
+	l := len(vs)
+	if l == 0 {
+		return
+	}
 	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"
 
 func (h *msghdr) setIov(vs []iovec) {
+	l := len(vs)
+	if l == 0 {
+		return
+	}
 	h.Iov = &vs[0]
-	h.Iovlen = uint32(len(vs))
+	h.Iovlen = uint32(l)
 }
 
 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"
 
 func (h *msghdr) setIov(vs []iovec) {
+	l := len(vs)
+	if l == 0 {
+		return
+	}
 	h.Iov = &vs[0]
-	h.Iovlen = uint64(len(vs))
+	h.Iovlen = uint64(l)
 }
 
 func (h *msghdr) setControl(b []byte) {

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

@@ -5,6 +5,10 @@
 package socket
 
 func (h *msghdr) setIov(vs []iovec) {
+	l := len(vs)
+	if l == 0 {
+		return
+	}
 	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 {
 		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 {
 		h.Accrights = (*int8)(unsafe.Pointer(&oob[0]))
 		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
 
 // Data returns the data field of the control message at the head on
-// w.
+// m.
 func (m ControlMessage) Data(dataLen int) []byte {
 	l := controlHeaderLen()
 	if len(m) < l || len(m) < l+dataLen {
@@ -119,7 +119,7 @@ func (m ControlMessage) Data(dataLen int) []byte {
 	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.
 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
-// the head on w.
+// the head on m.
 func (m ControlMessage) MarshalHeader(lvl, typ, dataLen int) error {
 	if len(m) < controlHeaderLen() {
 		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
-// message at the head on w.
+// message at the head on m.
 func (m ControlMessage) ParseHeader() (lvl, typ, dataLen int, err error) {
 	l := controlHeaderLen()
 	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
 }
 
-// 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.
 func (m ControlMessage) Marshal(lvl, typ int, data []byte) (ControlMessage, error) {
 	l := len(data)
@@ -167,7 +167,7 @@ func (m ControlMessage) Marshal(lvl, typ int, data []byte) (ControlMessage, erro
 	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.
 func (m ControlMessage) Parse() ([]ControlMessage, error) {
@@ -175,6 +175,9 @@ func (m ControlMessage) Parse() ([]ControlMessage, error) {
 	for len(m) >= controlHeaderLen() {
 		h := (*cmsghdr)(unsafe.Pointer(&m[0]))
 		l := h.len()
+		if l <= 0 {
+			return nil, errors.New("invalid header length")
+		}
 		if uint64(l) < uint64(controlHeaderLen()) {
 			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)
 	}
 	defer c.Close()
+	cc, err := socket.NewConn(c.(net.Conn))
+	if err != nil {
+		t.Fatal(err)
+	}
 
 	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 {
-	case "linux":
+	case "android", "linux":
 		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{
-		Buffers: bytes.SplitAfter(data, []byte("-")),
+		Buffers: [][]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)
-	}
-}
-
-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{
-		{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) {
@@ -230,7 +233,7 @@ func BenchmarkUDP(b *testing.B) {
 			}
 		})
 		switch runtime.GOOS {
-		case "linux":
+		case "android", "linux":
 			wms := make([]socket.Message, M)
 			for i := range wms {
 				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 {
 		b := make([]byte, sizeofSockaddrInet)
 		switch runtime.GOOS {
-		case "linux", "solaris", "windows":
+		case "android", "linux", "solaris", "windows":
 			NativeEndian.PutUint16(b[:2], uint16(sysAF_INET))
 		default:
 			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 {
 		b := make([]byte, sizeofSockaddrInet6)
 		switch runtime.GOOS {
-		case "linux", "solaris", "windows":
+		case "android", "linux", "solaris", "windows":
 			NativeEndian.PutUint16(b[:2], uint16(sysAF_INET6))
 		default:
 			b[0] = sizeofSockaddrInet6
@@ -69,7 +69,7 @@ func parseInetAddr(b []byte, network string) (net.Addr, error) {
 	}
 	var af int
 	switch runtime.GOOS {
-	case "linux", "solaris", "windows":
+	case "android", "linux", "solaris", "windows":
 		af = int(NativeEndian.Uint16(b[:2]))
 	default:
 		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
 }
 
+type mmsghdr struct {
+	Hdr msghdr
+	Len uint32
+}
+
 type cmsghdr struct {
 	Len   uint32
 	Level int32
@@ -52,6 +57,7 @@ type sockaddrInet6 struct {
 const (
 	sizeofIovec   = 0x8
 	sizeofMsghdr  = 0x1c
+	sizeofMmsghdr = 0x20
 	sizeofCmsghdr = 0xc
 
 	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 {
 			continue
 		}
-		switch typ {
-		case ctlOpts[ctlTTL].name:
+		switch {
+		case typ == ctlOpts[ctlTTL].name && l >= ctlOpts[ctlTTL].length:
 			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))
-		case ctlOpts[ctlInterface].name:
+		case typ == ctlOpts[ctlInterface].name && l >= ctlOpts[ctlInterface].length:
 			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))
 		}
 	}

+ 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
 }{
 	{
-		"http://www.iana.org/assignments/icmp-parameters/icmp-parameters.xml",
+		"https://www.iana.org/assignments/icmp-parameters/icmp-parameters.xml",
 		parseICMPv4Parameters,
 	},
 }
@@ -80,7 +80,7 @@ var registries = []struct {
 func geniana() error {
 	var bb bytes.Buffer
 	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")
 	for _, r := range registries {
 		resp, err := http.Get(r.url)

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