libgo: update to Go 1.14.6 release

Change-Id: I9566bc64907442242febeae37ab7548f8e8b4da9
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/243317
Reviewed-by: Cherry Zhang <cherryyz@google.com>
diff --git a/libgo/MERGE b/libgo/MERGE
index 07547d0..4f85893 100644
--- a/libgo/MERGE
+++ b/libgo/MERGE
@@ -1,4 +1,4 @@
-83b181c68bf332ac7948f145f33d128377a09c42
+edfd6f28486017dcb136cd3f3ec252706d4b326e
 
 The first line of this file holds the git revision number of the
 last merge done from the master library sources.
diff --git a/libgo/VERSION b/libgo/VERSION
index d8281a2..398d253 100644
--- a/libgo/VERSION
+++ b/libgo/VERSION
@@ -1 +1 @@
-go1.14.4
+go1.14.6
diff --git a/libgo/go/cmd/go/go_test.go b/libgo/go/cmd/go/go_test.go
index d535ea0..40999f2 100644
--- a/libgo/go/cmd/go/go_test.go
+++ b/libgo/go/cmd/go/go_test.go
@@ -3956,45 +3956,6 @@
 	tg.grepStderrNot(`"-L[^"]+c flags".*"-L[^"]+c flags"`, "found too many quoted ld flags")
 }
 
-// Issue 9737: verify that GOARM and GO386 affect the computed build ID.
-func TestBuildIDContainsArchModeEnv(t *testing.T) {
-	if testing.Short() {
-		t.Skip("skipping in short mode")
-	}
-
-	var tg *testgoData
-	testWith := func(before, after func()) func(*testing.T) {
-		return func(t *testing.T) {
-			tg = testgo(t)
-			defer tg.cleanup()
-			tg.tempFile("src/mycmd/x.go", `package main
-func main() {}`)
-			tg.setenv("GOPATH", tg.path("."))
-
-			tg.cd(tg.path("src/mycmd"))
-			tg.setenv("GOOS", "linux")
-			before()
-			tg.run("install", "mycmd")
-			after()
-			tg.wantStale("mycmd", "stale dependency", "should be stale after environment variable change")
-		}
-	}
-
-	t.Run("386", testWith(func() {
-		tg.setenv("GOARCH", "386")
-		tg.setenv("GO386", "387")
-	}, func() {
-		tg.setenv("GO386", "sse2")
-	}))
-
-	t.Run("arm", testWith(func() {
-		tg.setenv("GOARCH", "arm")
-		tg.setenv("GOARM", "5")
-	}, func() {
-		tg.setenv("GOARM", "7")
-	}))
-}
-
 func TestListTests(t *testing.T) {
 	tooSlow(t)
 	var tg *testgoData
diff --git a/libgo/go/cmd/go/testdata/test_regexps.txt b/libgo/go/cmd/go/testdata/test_regexps.txt
new file mode 100644
index 0000000..a616195
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/test_regexps.txt
@@ -0,0 +1,75 @@
+go test -cpu=1 -run=X/Y -bench=X/Y -count=2 -v testregexp
+
+# Test the following:
+
+# TestX is run, twice
+stdout -count=2 '^=== RUN   TestX$'
+stdout -count=2 '^    x_test.go:6: LOG: X running$'
+
+# TestX/Y is run, twice
+stdout -count=2 '^=== RUN   TestX/Y$'
+stdout -count=2 '^    x_test.go:8: LOG: Y running$'
+
+# TestXX is run, twice
+stdout -count=2 '^=== RUN   TestXX$'
+stdout -count=2 '^    z_test.go:10: LOG: XX running'
+
+# TestZ is not run
+! stdout '^=== RUN   TestZ$'
+
+# BenchmarkX is run with N=1 once, only to discover what sub-benchmarks it has,
+# and should not print a final summary line.
+stdout -count=1 '^    x_test.go:13: LOG: X running N=1$'
+! stdout '^\s+BenchmarkX: x_test.go:13: LOG: X running N=\d\d+'
+! stdout 'BenchmarkX\s+\d+'
+
+# Same for BenchmarkXX.
+stdout -count=1 '^    z_test.go:18: LOG: XX running N=1$'
+! stdout  '^    z_test.go:18: LOG: XX running N=\d\d+'
+! stdout 'BenchmarkXX\s+\d+'
+
+# BenchmarkX/Y is run in full twice due to -count=2.
+# "Run in full" means that it runs for approximately the default benchtime,
+# but may cap out at N=1e9.
+# We don't actually care what the final iteration count is, but it should be
+# a large number, and the last iteration count prints right before the results.
+stdout -count=2 '^    x_test.go:15: LOG: Y running N=[1-9]\d{4,}\nBenchmarkX/Y\s+\d+'
+
+-- testregexp/x_test.go --
+package x
+
+import "testing"
+
+func TestX(t *testing.T) {
+	t.Logf("LOG: X running")
+	t.Run("Y", func(t *testing.T) {
+		t.Logf("LOG: Y running")
+	})
+}
+
+func BenchmarkX(b *testing.B) {
+	b.Logf("LOG: X running N=%d", b.N)
+	b.Run("Y", func(b *testing.B) {
+		b.Logf("LOG: Y running N=%d", b.N)
+	})
+}
+-- testregexp/z_test.go --
+package x
+
+import "testing"
+
+func TestZ(t *testing.T) {
+	t.Logf("LOG: Z running")
+}
+
+func TestXX(t *testing.T) {
+	t.Logf("LOG: XX running")
+}
+
+func BenchmarkZ(b *testing.B) {
+	b.Logf("LOG: Z running N=%d", b.N)
+}
+
+func BenchmarkXX(b *testing.B) {
+	b.Logf("LOG: XX running N=%d", b.N)
+}
diff --git a/libgo/go/crypto/x509/root_windows.go b/libgo/go/crypto/x509/root_windows.go
index 34d5853..1e0f3ac 100644
--- a/libgo/go/crypto/x509/root_windows.go
+++ b/libgo/go/crypto/x509/root_windows.go
@@ -88,6 +88,9 @@
 		switch status {
 		case syscall.CERT_TRUST_IS_NOT_TIME_VALID:
 			return CertificateInvalidError{c, Expired, ""}
+		case syscall.CERT_TRUST_IS_NOT_VALID_FOR_USAGE:
+			return CertificateInvalidError{c, IncompatibleUsage, ""}
+		// TODO(filippo): surface more error statuses.
 		default:
 			return UnknownAuthorityError{c, nil, nil}
 		}
@@ -138,11 +141,19 @@
 	return nil
 }
 
+// windowsExtKeyUsageOIDs are the C NUL-terminated string representations of the
+// OIDs for use with the Windows API.
+var windowsExtKeyUsageOIDs = make(map[ExtKeyUsage][]byte, len(extKeyUsageOIDs))
+
+func init() {
+	for _, eku := range extKeyUsageOIDs {
+		windowsExtKeyUsageOIDs[eku.extKeyUsage] = []byte(eku.oid.String() + "\x00")
+	}
+}
+
 // systemVerify is like Verify, except that it uses CryptoAPI calls
 // to build certificate chains and verify them.
 func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
-	hasDNSName := opts != nil && len(opts.DNSName) > 0
-
 	storeCtx, err := createStoreContext(c, opts)
 	if err != nil {
 		return nil, err
@@ -152,17 +163,26 @@
 	para := new(syscall.CertChainPara)
 	para.Size = uint32(unsafe.Sizeof(*para))
 
-	// If there's a DNSName set in opts, assume we're verifying
-	// a certificate from a TLS server.
-	if hasDNSName {
-		oids := []*byte{
-			&syscall.OID_PKIX_KP_SERVER_AUTH[0],
-			// Both IE and Chrome allow certificates with
-			// Server Gated Crypto as well. Some certificates
-			// in the wild require them.
-			&syscall.OID_SERVER_GATED_CRYPTO[0],
-			&syscall.OID_SGC_NETSCAPE[0],
+	keyUsages := opts.KeyUsages
+	if len(keyUsages) == 0 {
+		keyUsages = []ExtKeyUsage{ExtKeyUsageServerAuth}
+	}
+	oids := make([]*byte, 0, len(keyUsages))
+	for _, eku := range keyUsages {
+		if eku == ExtKeyUsageAny {
+			oids = nil
+			break
 		}
+		if oid, ok := windowsExtKeyUsageOIDs[eku]; ok {
+			oids = append(oids, &oid[0])
+		}
+		// Like the standard verifier, accept SGC EKUs as equivalent to ServerAuth.
+		if eku == ExtKeyUsageServerAuth {
+			oids = append(oids, &syscall.OID_SERVER_GATED_CRYPTO[0])
+			oids = append(oids, &syscall.OID_SGC_NETSCAPE[0])
+		}
+	}
+	if oids != nil {
 		para.RequestedUsage.Type = syscall.USAGE_MATCH_TYPE_OR
 		para.RequestedUsage.Usage.Length = uint32(len(oids))
 		para.RequestedUsage.Usage.UsageIdentifiers = &oids[0]
@@ -208,7 +228,7 @@
 		return nil, err
 	}
 
-	if hasDNSName {
+	if opts != nil && len(opts.DNSName) > 0 {
 		err = checkChainSSLServerPolicy(c, chainCtx, opts)
 		if err != nil {
 			return nil, err
diff --git a/libgo/go/crypto/x509/verify.go b/libgo/go/crypto/x509/verify.go
index 358fca4..c80b5ac 100644
--- a/libgo/go/crypto/x509/verify.go
+++ b/libgo/go/crypto/x509/verify.go
@@ -188,23 +188,32 @@
 // VerifyOptions contains parameters for Certificate.Verify. It's a structure
 // because other PKIX verification APIs have ended up needing many options.
 type VerifyOptions struct {
-	DNSName       string
+	// DNSName, if set, is checked against the leaf certificate with
+	// Certificate.VerifyHostname or the platform verifier.
+	DNSName string
+
+	// Intermediates is an optional pool of certificates that are not trust
+	// anchors, but can be used to form a chain from the leaf certificate to a
+	// root certificate.
 	Intermediates *CertPool
-	Roots         *CertPool // if nil, the system roots are used
-	CurrentTime   time.Time // if zero, the current time is used
-	// KeyUsage specifies which Extended Key Usage values are acceptable. A leaf
-	// certificate is accepted if it contains any of the listed values. An empty
-	// list means ExtKeyUsageServerAuth. To accept any key usage, include
-	// ExtKeyUsageAny.
-	//
-	// Certificate chains are required to nest these extended key usage values.
-	// (This matches the Windows CryptoAPI behavior, but not the spec.)
+	// Roots is the set of trusted root certificates the leaf certificate needs
+	// to chain up to. If nil, the system roots or the platform verifier are used.
+	Roots *CertPool
+
+	// CurrentTime is used to check the validity of all certificates in the
+	// chain. If zero, the current time is used.
+	CurrentTime time.Time
+
+	// KeyUsages specifies which Extended Key Usage values are acceptable. A
+	// chain is accepted if it allows any of the listed values. An empty list
+	// means ExtKeyUsageServerAuth. To accept any key usage, include ExtKeyUsageAny.
 	KeyUsages []ExtKeyUsage
+
 	// MaxConstraintComparisions is the maximum number of comparisons to
 	// perform when checking a given certificate's name constraints. If
 	// zero, a sensible default is used. This limit prevents pathological
 	// certificates from consuming excessive amounts of CPU time when
-	// validating.
+	// validating. It does not apply to the platform verifier.
 	MaxConstraintComparisions int
 }
 
@@ -717,8 +726,9 @@
 // needed. If successful, it returns one or more chains where the first
 // element of the chain is c and the last element is from opts.Roots.
 //
-// If opts.Roots is nil and system roots are unavailable the returned error
-// will be of type SystemRootsError.
+// If opts.Roots is nil, the platform verifier might be used, and
+// verification details might differ from what is described below. If system
+// roots are unavailable the returned error will be of type SystemRootsError.
 //
 // Name constraints in the intermediates will be applied to all names claimed
 // in the chain, not just opts.DNSName. Thus it is invalid for a leaf to claim
@@ -726,9 +736,10 @@
 // the name being validated. Note that DirectoryName constraints are not
 // supported.
 //
-// Extended Key Usage values are enforced down a chain, so an intermediate or
-// root that enumerates EKUs prevents a leaf from asserting an EKU not in that
-// list.
+// Extended Key Usage values are enforced nested down a chain, so an intermediate
+// or root that enumerates EKUs prevents a leaf from asserting an EKU not in that
+// list. (While this is not specified, it is common practice in order to limit
+// the types of certificates a CA can issue.)
 //
 // WARNING: this function doesn't do any revocation checking.
 func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err error) {
diff --git a/libgo/go/crypto/x509/verify_test.go b/libgo/go/crypto/x509/verify_test.go
index 86fe76a..bbb68db 100644
--- a/libgo/go/crypto/x509/verify_test.go
+++ b/libgo/go/crypto/x509/verify_test.go
@@ -21,34 +21,24 @@
 )
 
 type verifyTest struct {
-	leaf                 string
-	intermediates        []string
-	roots                []string
-	currentTime          int64
-	dnsName              string
-	systemSkip           bool
-	keyUsages            []ExtKeyUsage
-	testSystemRootsError bool
-	sha2                 bool
-	ignoreCN             bool
+	name          string
+	leaf          string
+	intermediates []string
+	roots         []string
+	currentTime   int64
+	dnsName       string
+	systemSkip    bool
+	systemLax     bool
+	keyUsages     []ExtKeyUsage
+	ignoreCN      bool
 
-	errorCallback  func(*testing.T, int, error) bool
+	errorCallback  func(*testing.T, error)
 	expectedChains [][]string
 }
 
 var verifyTests = []verifyTest{
 	{
-		leaf:                 googleLeaf,
-		intermediates:        []string{giag2Intermediate},
-		currentTime:          1395785200,
-		dnsName:              "www.google.com",
-		testSystemRootsError: true,
-
-		// Without any roots specified we should get a system roots
-		// error.
-		errorCallback: expectSystemRootsError,
-	},
-	{
+		name:          "Valid",
 		leaf:          googleLeaf,
 		intermediates: []string{giag2Intermediate},
 		roots:         []string{geoTrustRoot},
@@ -60,6 +50,7 @@
 		},
 	},
 	{
+		name:          "MixedCase",
 		leaf:          googleLeaf,
 		intermediates: []string{giag2Intermediate},
 		roots:         []string{geoTrustRoot},
@@ -71,6 +62,7 @@
 		},
 	},
 	{
+		name:          "HostnameMismatch",
 		leaf:          googleLeaf,
 		intermediates: []string{giag2Intermediate},
 		roots:         []string{geoTrustRoot},
@@ -80,6 +72,7 @@
 		errorCallback: expectHostnameError("certificate is valid for"),
 	},
 	{
+		name:          "IPMissing",
 		leaf:          googleLeaf,
 		intermediates: []string{giag2Intermediate},
 		roots:         []string{geoTrustRoot},
@@ -89,6 +82,7 @@
 		errorCallback: expectHostnameError("doesn't contain any IP SANs"),
 	},
 	{
+		name:          "Expired",
 		leaf:          googleLeaf,
 		intermediates: []string{giag2Intermediate},
 		roots:         []string{geoTrustRoot},
@@ -98,6 +92,7 @@
 		errorCallback: expectExpired,
 	},
 	{
+		name:        "MissingIntermediate",
 		leaf:        googleLeaf,
 		roots:       []string{geoTrustRoot},
 		currentTime: 1395785200,
@@ -109,6 +104,7 @@
 		errorCallback: expectAuthorityUnknown,
 	},
 	{
+		name:          "RootInIntermediates",
 		leaf:          googleLeaf,
 		intermediates: []string{geoTrustRoot, giag2Intermediate},
 		roots:         []string{geoTrustRoot},
@@ -119,31 +115,50 @@
 			{"Google", "Google Internet Authority", "GeoTrust"},
 		},
 		// CAPI doesn't build the chain with the duplicated GeoTrust
-		// entry so the results don't match. Thus we skip this test
-		// until that's fixed.
-		systemSkip: true,
+		// entry so the results don't match.
+		systemLax: true,
 	},
 	{
+		name:          "dnssec-exp",
 		leaf:          dnssecExpLeaf,
 		intermediates: []string{startComIntermediate},
 		roots:         []string{startComRoot},
 		currentTime:   1302726541,
 
-		expectedChains: [][]string{
-			{"dnssec-exp", "StartCom Class 1", "StartCom Certification Authority"},
-		},
-	},
-	{
-		leaf:          dnssecExpLeaf,
-		intermediates: []string{startComIntermediate, startComRoot},
-		roots:         []string{startComRoot},
-		currentTime:   1302726541,
+		// The StartCom root is not trusted by Windows when the default
+		// ServerAuth EKU is requested.
+		systemSkip: true,
 
 		expectedChains: [][]string{
 			{"dnssec-exp", "StartCom Class 1", "StartCom Certification Authority"},
 		},
 	},
 	{
+		name:          "dnssec-exp/AnyEKU",
+		leaf:          dnssecExpLeaf,
+		intermediates: []string{startComIntermediate},
+		roots:         []string{startComRoot},
+		currentTime:   1302726541,
+		keyUsages:     []ExtKeyUsage{ExtKeyUsageAny},
+
+		expectedChains: [][]string{
+			{"dnssec-exp", "StartCom Class 1", "StartCom Certification Authority"},
+		},
+	},
+	{
+		name:          "dnssec-exp/RootInIntermediates",
+		leaf:          dnssecExpLeaf,
+		intermediates: []string{startComIntermediate, startComRoot},
+		roots:         []string{startComRoot},
+		currentTime:   1302726541,
+		systemSkip:    true, // see dnssec-exp test
+
+		expectedChains: [][]string{
+			{"dnssec-exp", "StartCom Class 1", "StartCom Certification Authority"},
+		},
+	},
+	{
+		name:          "InvalidHash",
 		leaf:          googleLeafWithInvalidHash,
 		intermediates: []string{giag2Intermediate},
 		roots:         []string{geoTrustRoot},
@@ -152,50 +167,52 @@
 
 		// The specific error message may not occur when using system
 		// verification.
-		systemSkip:    true,
+		systemLax:     true,
 		errorCallback: expectHashError,
 	},
+	// EKULeaf tests use an unconstrained chain leading to a leaf certificate
+	// with an E-mail Protection EKU but not a Server Auth one, checking that
+	// the EKUs on the leaf are enforced.
 	{
-		// The default configuration should reject an S/MIME chain.
-		leaf:        smimeLeaf,
-		roots:       []string{smimeIntermediate},
-		currentTime: 1339436154,
+		name:          "EKULeaf",
+		leaf:          smimeLeaf,
+		intermediates: []string{smimeIntermediate},
+		roots:         []string{smimeRoot},
+		currentTime:   1594673418,
 
-		// Key usage not implemented for Windows yet.
-		systemSkip:    true,
 		errorCallback: expectUsageError,
 	},
 	{
-		leaf:        smimeLeaf,
-		roots:       []string{smimeIntermediate},
-		currentTime: 1339436154,
-		keyUsages:   []ExtKeyUsage{ExtKeyUsageServerAuth},
+		name:          "EKULeafExplicit",
+		leaf:          smimeLeaf,
+		intermediates: []string{smimeIntermediate},
+		roots:         []string{smimeRoot},
+		currentTime:   1594673418,
+		keyUsages:     []ExtKeyUsage{ExtKeyUsageServerAuth},
 
-		// Key usage not implemented for Windows yet.
-		systemSkip:    true,
 		errorCallback: expectUsageError,
 	},
 	{
-		leaf:        smimeLeaf,
-		roots:       []string{smimeIntermediate},
-		currentTime: 1339436154,
-		keyUsages:   []ExtKeyUsage{ExtKeyUsageEmailProtection},
+		name:          "EKULeafValid",
+		leaf:          smimeLeaf,
+		intermediates: []string{smimeIntermediate},
+		roots:         []string{smimeRoot},
+		currentTime:   1594673418,
+		keyUsages:     []ExtKeyUsage{ExtKeyUsageEmailProtection},
 
-		// Key usage not implemented for Windows yet.
-		systemSkip: true,
 		expectedChains: [][]string{
-			{"Ryan Hurst", "GlobalSign PersonalSign 2 CA - G2"},
+			{"CORPORATIVO FICTICIO ACTIVO", "EAEko Herri Administrazioen CA - CA AAPP Vascas (2)", "IZENPE S.A."},
 		},
 	},
 	{
+		name:          "SGCIntermediate",
 		leaf:          megaLeaf,
 		intermediates: []string{comodoIntermediate1},
 		roots:         []string{comodoRoot},
 		currentTime:   1360431182,
 
-		// CryptoAPI can find alternative validation paths so we don't
-		// perform this test with system validation.
-		systemSkip: true,
+		// CryptoAPI can find alternative validation paths.
+		systemLax: true,
 		expectedChains: [][]string{
 			{"mega.co.nz", "EssentialSSL CA", "COMODO Certification Authority"},
 		},
@@ -203,6 +220,7 @@
 	{
 		// Check that a name constrained intermediate works even when
 		// it lists multiple constraints.
+		name:          "MultipleConstraints",
 		leaf:          nameConstraintsLeaf,
 		intermediates: []string{nameConstraintsIntermediate1, nameConstraintsIntermediate2},
 		roots:         []string{globalSignRoot},
@@ -221,17 +239,16 @@
 	{
 		// Check that SHA-384 intermediates (which are popping up)
 		// work.
+		name:          "SHA-384",
 		leaf:          moipLeafCert,
 		intermediates: []string{comodoIntermediateSHA384, comodoRSAAuthority},
 		roots:         []string{addTrustRoot},
 		currentTime:   1397502195,
 		dnsName:       "api.moip.com.br",
 
-		// CryptoAPI can find alternative validation paths so we don't
-		// perform this test with system validation.
-		systemSkip: true,
+		// CryptoAPI can find alternative validation paths.
+		systemLax: true,
 
-		sha2: true,
 		expectedChains: [][]string{
 			{
 				"api.moip.com.br",
@@ -244,11 +261,12 @@
 	{
 		// Putting a certificate as a root directly should work as a
 		// way of saying “exactly this”.
+		name:        "LeafInRoots",
 		leaf:        selfSigned,
 		roots:       []string{selfSigned},
 		currentTime: 1471624472,
 		dnsName:     "foo.example",
-		systemSkip:  true,
+		systemSkip:  true, // does not chain to a system root
 
 		expectedChains: [][]string{
 			{"Acme Co"},
@@ -257,11 +275,12 @@
 	{
 		// Putting a certificate as a root directly should not skip
 		// other checks however.
+		name:        "LeafInRootsInvalid",
 		leaf:        selfSigned,
 		roots:       []string{selfSigned},
 		currentTime: 1471624472,
 		dnsName:     "notfoo.example",
-		systemSkip:  true,
+		systemSkip:  true, // does not chain to a system root
 
 		errorCallback: expectHostnameError("certificate is valid for"),
 	},
@@ -269,87 +288,95 @@
 		// The issuer name in the leaf doesn't exactly match the
 		// subject name in the root. Go does not perform
 		// canonicalization and so should reject this. See issue 14955.
+		name:        "IssuerSubjectMismatch",
 		leaf:        issuerSubjectMatchLeaf,
 		roots:       []string{issuerSubjectMatchRoot},
 		currentTime: 1475787715,
-		systemSkip:  true,
+		systemSkip:  true, // does not chain to a system root
 
 		errorCallback: expectSubjectIssuerMismatcthError,
 	},
 	{
 		// An X.509 v1 certificate should not be accepted as an
 		// intermediate.
+		name:          "X509v1Intermediate",
 		leaf:          x509v1TestLeaf,
 		intermediates: []string{x509v1TestIntermediate},
 		roots:         []string{x509v1TestRoot},
 		currentTime:   1481753183,
-		systemSkip:    true,
+		systemSkip:    true, // does not chain to a system root
 
 		errorCallback: expectNotAuthorizedError,
 	},
 	{
 		// If any SAN extension is present (even one without any DNS
 		// names), the CN should be ignored.
+		name:        "IgnoreCNWithSANs",
 		leaf:        ignoreCNWithSANLeaf,
 		dnsName:     "foo.example.com",
 		roots:       []string{ignoreCNWithSANRoot},
 		currentTime: 1486684488,
-		systemSkip:  true,
+		systemSkip:  true, // does not chain to a system root
 
 		errorCallback: expectHostnameError("certificate is not valid for any names"),
 	},
 	{
 		// Test that excluded names are respected.
+		name:          "ExcludedNames",
 		leaf:          excludedNamesLeaf,
 		dnsName:       "bender.local",
 		intermediates: []string{excludedNamesIntermediate},
 		roots:         []string{excludedNamesRoot},
 		currentTime:   1486684488,
-		systemSkip:    true,
+		systemSkip:    true, // does not chain to a system root
 
 		errorCallback: expectNameConstraintsError,
 	},
 	{
 		// Test that unknown critical extensions in a leaf cause a
 		// verify error.
+		name:          "CriticalExtLeaf",
 		leaf:          criticalExtLeafWithExt,
 		dnsName:       "example.com",
 		intermediates: []string{criticalExtIntermediate},
 		roots:         []string{criticalExtRoot},
 		currentTime:   1486684488,
-		systemSkip:    true,
+		systemSkip:    true, // does not chain to a system root
 
 		errorCallback: expectUnhandledCriticalExtension,
 	},
 	{
 		// Test that unknown critical extensions in an intermediate
 		// cause a verify error.
+		name:          "CriticalExtIntermediate",
 		leaf:          criticalExtLeaf,
 		dnsName:       "example.com",
 		intermediates: []string{criticalExtIntermediateWithExt},
 		roots:         []string{criticalExtRoot},
 		currentTime:   1486684488,
-		systemSkip:    true,
+		systemSkip:    true, // does not chain to a system root
 
 		errorCallback: expectUnhandledCriticalExtension,
 	},
 	{
 		// Test that invalid CN are ignored.
+		name:        "InvalidCN",
 		leaf:        invalidCNWithoutSAN,
 		dnsName:     "foo,invalid",
 		roots:       []string{invalidCNRoot},
 		currentTime: 1540000000,
-		systemSkip:  true,
+		systemSkip:  true, // does not chain to a system root
 
 		errorCallback: expectHostnameError("Common Name is not a valid hostname"),
 	},
 	{
 		// Test that valid CN are respected.
+		name:        "ValidCN",
 		leaf:        validCNWithoutSAN,
 		dnsName:     "foo.example.com",
 		roots:       []string{invalidCNRoot},
 		currentTime: 1540000000,
-		systemSkip:  true,
+		systemSkip:  true, // does not chain to a system root
 
 		expectedChains: [][]string{
 			{"foo.example.com", "Test root"},
@@ -357,31 +384,34 @@
 	},
 	// Replicate CN tests with ignoreCN = true
 	{
+		name:        "IgnoreCNWithSANs/ignoreCN",
 		leaf:        ignoreCNWithSANLeaf,
 		dnsName:     "foo.example.com",
 		roots:       []string{ignoreCNWithSANRoot},
 		currentTime: 1486684488,
-		systemSkip:  true,
+		systemSkip:  true, // does not chain to a system root
 		ignoreCN:    true,
 
 		errorCallback: expectHostnameError("certificate is not valid for any names"),
 	},
 	{
+		name:        "InvalidCN/ignoreCN",
 		leaf:        invalidCNWithoutSAN,
 		dnsName:     "foo,invalid",
 		roots:       []string{invalidCNRoot},
 		currentTime: 1540000000,
-		systemSkip:  true,
+		systemSkip:  true, // does not chain to a system root
 		ignoreCN:    true,
 
 		errorCallback: expectHostnameError("Common Name is not a valid hostname"),
 	},
 	{
+		name:        "ValidCN/ignoreCN",
 		leaf:        validCNWithoutSAN,
 		dnsName:     "foo.example.com",
 		roots:       []string{invalidCNRoot},
 		currentTime: 1540000000,
-		systemSkip:  true,
+		systemSkip:  true, // does not chain to a system root
 		ignoreCN:    true,
 
 		errorCallback: expectHostnameError("not valid for any names"),
@@ -389,11 +419,12 @@
 	{
 		// A certificate with an AKID should still chain to a parent without SKID.
 		// See Issue 30079.
+		name:        "AKIDNoSKID",
 		leaf:        leafWithAKID,
 		roots:       []string{rootWithoutSKID},
 		currentTime: 1550000000,
 		dnsName:     "example",
-		systemSkip:  true,
+		systemSkip:  true, // does not chain to a system root
 
 		expectedChains: [][]string{
 			{"Acme LLC", "Acme Co"},
@@ -401,98 +432,70 @@
 	},
 }
 
-func expectHostnameError(msg string) func(*testing.T, int, error) bool {
-	return func(t *testing.T, i int, err error) (ok bool) {
+func expectHostnameError(msg string) func(*testing.T, error) {
+	return func(t *testing.T, err error) {
 		if _, ok := err.(HostnameError); !ok {
-			t.Errorf("#%d: error was not a HostnameError: %v", i, err)
-			return false
+			t.Fatalf("error was not a HostnameError: %v", err)
 		}
 		if !strings.Contains(err.Error(), msg) {
-			t.Errorf("#%d: HostnameError did not contain %q: %v", i, msg, err)
+			t.Fatalf("HostnameError did not contain %q: %v", msg, err)
 		}
-		return true
 	}
 }
 
-func expectExpired(t *testing.T, i int, err error) (ok bool) {
+func expectExpired(t *testing.T, err error) {
 	if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != Expired {
-		t.Errorf("#%d: error was not Expired: %v", i, err)
-		return false
+		t.Fatalf("error was not Expired: %v", err)
 	}
-	return true
 }
 
-func expectUsageError(t *testing.T, i int, err error) (ok bool) {
+func expectUsageError(t *testing.T, err error) {
 	if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != IncompatibleUsage {
-		t.Errorf("#%d: error was not IncompatibleUsage: %v", i, err)
-		return false
+		t.Fatalf("error was not IncompatibleUsage: %v", err)
 	}
-	return true
 }
 
-func expectAuthorityUnknown(t *testing.T, i int, err error) (ok bool) {
+func expectAuthorityUnknown(t *testing.T, err error) {
 	e, ok := err.(UnknownAuthorityError)
 	if !ok {
-		t.Errorf("#%d: error was not UnknownAuthorityError: %v", i, err)
-		return false
+		t.Fatalf("error was not UnknownAuthorityError: %v", err)
 	}
 	if e.Cert == nil {
-		t.Errorf("#%d: error was UnknownAuthorityError, but missing Cert: %v", i, err)
-		return false
+		t.Fatalf("error was UnknownAuthorityError, but missing Cert: %v", err)
 	}
-	return true
 }
 
-func expectSystemRootsError(t *testing.T, i int, err error) bool {
-	if _, ok := err.(SystemRootsError); !ok {
-		t.Errorf("#%d: error was not SystemRootsError: %v", i, err)
-		return false
-	}
-	return true
-}
-
-func expectHashError(t *testing.T, i int, err error) bool {
+func expectHashError(t *testing.T, err error) {
 	if err == nil {
-		t.Errorf("#%d: no error resulted from invalid hash", i)
-		return false
+		t.Fatalf("no error resulted from invalid hash")
 	}
 	if expected := "algorithm unimplemented"; !strings.Contains(err.Error(), expected) {
-		t.Errorf("#%d: error resulting from invalid hash didn't contain '%s', rather it was: %v", i, expected, err)
-		return false
+		t.Fatalf("error resulting from invalid hash didn't contain '%s', rather it was: %v", expected, err)
 	}
-	return true
 }
 
-func expectSubjectIssuerMismatcthError(t *testing.T, i int, err error) (ok bool) {
+func expectSubjectIssuerMismatcthError(t *testing.T, err error) {
 	if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != NameMismatch {
-		t.Errorf("#%d: error was not a NameMismatch: %v", i, err)
-		return false
+		t.Fatalf("error was not a NameMismatch: %v", err)
 	}
-	return true
 }
 
-func expectNameConstraintsError(t *testing.T, i int, err error) (ok bool) {
+func expectNameConstraintsError(t *testing.T, err error) {
 	if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != CANotAuthorizedForThisName {
-		t.Errorf("#%d: error was not a CANotAuthorizedForThisName: %v", i, err)
-		return false
+		t.Fatalf("error was not a CANotAuthorizedForThisName: %v", err)
 	}
-	return true
 }
 
-func expectNotAuthorizedError(t *testing.T, i int, err error) (ok bool) {
+func expectNotAuthorizedError(t *testing.T, err error) {
 	if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != NotAuthorizedToSign {
-		t.Errorf("#%d: error was not a NotAuthorizedToSign: %v", i, err)
-		return false
+		t.Fatalf("error was not a NotAuthorizedToSign: %v", err)
 	}
-	return true
 }
 
-func expectUnhandledCriticalExtension(t *testing.T, i int, err error) (ok bool) {
+func expectUnhandledCriticalExtension(t *testing.T, err error) {
 	if _, ok := err.(UnhandledCriticalExtension); !ok {
-		t.Errorf("#%d: error was not an UnhandledCriticalExtension: %v", i, err)
-		return false
+		t.Fatalf("error was not an UnhandledCriticalExtension: %v", err)
 	}
-	return true
 }
 
 func certificateFromPEM(pemBytes string) (*Certificate, error) {
@@ -503,107 +506,91 @@
 	return ParseCertificate(block.Bytes)
 }
 
-func testVerify(t *testing.T, useSystemRoots bool) {
-	defer func(savedIgnoreCN bool) {
-		ignoreCN = savedIgnoreCN
-	}(ignoreCN)
-	for i, test := range verifyTests {
-		if useSystemRoots && test.systemSkip {
-			continue
-		}
-		if runtime.GOOS == "windows" && test.testSystemRootsError {
-			continue
-		}
+func testVerify(t *testing.T, test verifyTest, useSystemRoots bool) {
+	defer func(savedIgnoreCN bool) { ignoreCN = savedIgnoreCN }(ignoreCN)
 
-		ignoreCN = test.ignoreCN
-		opts := VerifyOptions{
-			Intermediates: NewCertPool(),
-			DNSName:       test.dnsName,
-			CurrentTime:   time.Unix(test.currentTime, 0),
-			KeyUsages:     test.keyUsages,
-		}
+	ignoreCN = test.ignoreCN
+	opts := VerifyOptions{
+		Intermediates: NewCertPool(),
+		DNSName:       test.dnsName,
+		CurrentTime:   time.Unix(test.currentTime, 0),
+		KeyUsages:     test.keyUsages,
+	}
 
-		if !useSystemRoots {
-			opts.Roots = NewCertPool()
-			for j, root := range test.roots {
-				ok := opts.Roots.AppendCertsFromPEM([]byte(root))
-				if !ok {
-					t.Errorf("#%d: failed to parse root #%d", i, j)
-					return
-				}
-			}
-		}
-
-		for j, intermediate := range test.intermediates {
-			ok := opts.Intermediates.AppendCertsFromPEM([]byte(intermediate))
+	if !useSystemRoots {
+		opts.Roots = NewCertPool()
+		for j, root := range test.roots {
+			ok := opts.Roots.AppendCertsFromPEM([]byte(root))
 			if !ok {
-				t.Errorf("#%d: failed to parse intermediate #%d", i, j)
-				return
+				t.Fatalf("failed to parse root #%d", j)
 			}
 		}
+	}
 
-		leaf, err := certificateFromPEM(test.leaf)
-		if err != nil {
-			t.Errorf("#%d: failed to parse leaf: %v", i, err)
-			return
+	for j, intermediate := range test.intermediates {
+		ok := opts.Intermediates.AppendCertsFromPEM([]byte(intermediate))
+		if !ok {
+			t.Fatalf("failed to parse intermediate #%d", j)
 		}
+	}
 
-		var oldSystemRoots *CertPool
-		if test.testSystemRootsError {
-			oldSystemRoots = systemRootsPool()
-			systemRoots = nil
-			opts.Roots = nil
-		}
+	leaf, err := certificateFromPEM(test.leaf)
+	if err != nil {
+		t.Fatalf("failed to parse leaf: %v", err)
+	}
 
-		chains, err := leaf.Verify(opts)
+	chains, err := leaf.Verify(opts)
 
-		if test.testSystemRootsError {
-			systemRoots = oldSystemRoots
-		}
-
-		if test.errorCallback == nil && err != nil {
-			t.Errorf("#%d: unexpected error: %v", i, err)
-		}
-		if test.errorCallback != nil {
-			if !test.errorCallback(t, i, err) {
-				return
+	if test.errorCallback == nil && err != nil {
+		t.Fatalf("unexpected error: %v", err)
+	}
+	if test.errorCallback != nil {
+		if useSystemRoots && test.systemLax {
+			if err == nil {
+				t.Fatalf("expected error")
 			}
+		} else {
+			test.errorCallback(t, err)
 		}
+	}
 
-		if len(chains) != len(test.expectedChains) {
-			t.Errorf("#%d: wanted %d chains, got %d", i, len(test.expectedChains), len(chains))
-		}
+	if len(chains) != len(test.expectedChains) {
+		t.Errorf("wanted %d chains, got %d", len(test.expectedChains), len(chains))
+	}
 
-		// We check that each returned chain matches a chain from
-		// expectedChains but an entry in expectedChains can't match
-		// two chains.
-		seenChains := make([]bool, len(chains))
-	NextOutputChain:
-		for _, chain := range chains {
-		TryNextExpected:
-			for j, expectedChain := range test.expectedChains {
-				if seenChains[j] {
-					continue
-				}
-				if len(chain) != len(expectedChain) {
-					continue
-				}
-				for k, cert := range chain {
-					if !strings.Contains(nameToKey(&cert.Subject), expectedChain[k]) {
-						continue TryNextExpected
-					}
-				}
-				// we matched
-				seenChains[j] = true
-				continue NextOutputChain
+	// We check that each returned chain matches a chain from
+	// expectedChains but an entry in expectedChains can't match
+	// two chains.
+	seenChains := make([]bool, len(chains))
+NextOutputChain:
+	for _, chain := range chains {
+	TryNextExpected:
+		for j, expectedChain := range test.expectedChains {
+			if seenChains[j] {
+				continue
 			}
-			t.Errorf("#%d: No expected chain matched %s", i, chainToDebugString(chain))
+			if len(chain) != len(expectedChain) {
+				continue
+			}
+			for k, cert := range chain {
+				if !strings.Contains(nameToKey(&cert.Subject), expectedChain[k]) {
+					continue TryNextExpected
+				}
+			}
+			// we matched
+			seenChains[j] = true
+			continue NextOutputChain
 		}
+		t.Errorf("no expected chain matched %s", chainToDebugString(chain))
 	}
 }
 
 func TestGoVerify(t *testing.T) {
-	testVerify(t, false)
+	for _, test := range verifyTests {
+		t.Run(test.name, func(t *testing.T) {
+			testVerify(t, test, false)
+		})
+	}
 }
 
 func TestSystemVerify(t *testing.T) {
@@ -611,7 +598,14 @@
 		t.Skipf("skipping verify test using system APIs on %q", runtime.GOOS)
 	}
 
-	testVerify(t, true)
+	for _, test := range verifyTests {
+		t.Run(test.name, func(t *testing.T) {
+			if test.systemSkip {
+				t.SkipNow()
+			}
+			testVerify(t, test, true)
+		})
+	}
 }
 
 func chainToDebugString(chain []*Certificate) string {
@@ -648,8 +642,7 @@
 PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un
 hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV
 5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw==
------END CERTIFICATE-----
-`
+-----END CERTIFICATE-----`
 
 const giag2Intermediate = `-----BEGIN CERTIFICATE-----
 MIIEBDCCAuygAwIBAgIDAjppMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT
@@ -674,8 +667,7 @@
 HFa9llF7b1cq26KqltyMdMKVvvBulRP/F/A8rLIQjcxz++iPAsbw+zOzlTvjwsto
 WHPbqCRiOwY1nQ2pM714A5AuTHhdUDqB1O6gyHA43LL5Z/qHQF1hwFGPa4NrzQU6
 yuGnBXj8ytqU0CwIPX4WecigUCAkVDNx
------END CERTIFICATE-----
-`
+-----END CERTIFICATE-----`
 
 const googleLeaf = `-----BEGIN CERTIFICATE-----
 MIIEdjCCA16gAwIBAgIIcR5k4dkoe04wDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UE
@@ -702,8 +694,7 @@
 orKqTuAPzXK7imQk6+OycYABbqCtC/9qmwRd8wwn7sF97DtYfK8WuNHtFalCAwyi
 8LxJJYJCLWoMhZ+V8GZm+FOex5qkQAjnZrtNlbQJ8ro4r+rpKXtmMFFhfa+7L+PA
 Kom08eUK8skxAzfDDijZPh10VtJ66uBoiDPdT+uCBehcBIcmSTrKjFGX
------END CERTIFICATE-----
-`
+-----END CERTIFICATE-----`
 
 // googleLeafWithInvalidHash is the same as googleLeaf, but the signature
 // algorithm in the certificate contains a nonsense OID.
@@ -732,8 +723,7 @@
 orKqTuAPzXK7imQk6+OycYABbqCtC/9qmwRd8wwn7sF97DtYfK8WuNHtFalCAwyi
 8LxJJYJCLWoMhZ+V8GZm+FOex5qkQAjnZrtNlbQJ8ro4r+rpKXtmMFFhfa+7L+PA
 Kom08eUK8skxAzfDDijZPh10VtJ66uBoiDPdT+uCBehcBIcmSTrKjFGX
------END CERTIFICATE-----
-`
+-----END CERTIFICATE-----`
 
 const dnssecExpLeaf = `-----BEGIN CERTIFICATE-----
 MIIGzTCCBbWgAwIBAgIDAdD6MA0GCSqGSIb3DQEBBQUAMIGMMQswCQYDVQQGEwJJ
@@ -858,58 +848,127 @@
 -----END CERTIFICATE-----`
 
 const smimeLeaf = `-----BEGIN CERTIFICATE-----
-MIIFBjCCA+6gAwIBAgISESFvrjT8XcJTEe6rBlPptILlMA0GCSqGSIb3DQEBBQUA
-MFQxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMSowKAYD
-VQQDEyFHbG9iYWxTaWduIFBlcnNvbmFsU2lnbiAyIENBIC0gRzIwHhcNMTIwMTIz
-MTYzNjU5WhcNMTUwMTIzMTYzNjU5WjCBlDELMAkGA1UEBhMCVVMxFjAUBgNVBAgT
-DU5ldyBIYW1zcGhpcmUxEzARBgNVBAcTClBvcnRzbW91dGgxGTAXBgNVBAoTEEds
-b2JhbFNpZ24sIEluYy4xEzARBgNVBAMTClJ5YW4gSHVyc3QxKDAmBgkqhkiG9w0B
-CQEWGXJ5YW4uaHVyc3RAZ2xvYmFsc2lnbi5jb20wggEiMA0GCSqGSIb3DQEBAQUA
-A4IBDwAwggEKAoIBAQC4ASSTvavmsFQAob60ukSSwOAL9nT/s99ltNUCAf5fPH5j
-NceMKxaQse2miOmRRIXaykcq1p/TbI70Ztce38r2mbOwqDHHPVi13GxJEyUXWgaR
-BteDMu5OGyWNG1kchVsGWpbstT0Z4v0md5m1BYFnxB20ebJyOR2lXDxsFK28nnKV
-+5eMj76U8BpPQ4SCH7yTMG6y0XXsB3cCrBKr2o3TOYgEKv+oNnbaoMt3UxMt9nSf
-9jyIshjqfnT5Aew3CUNMatO55g5FXXdIukAweg1YSb1ls05qW3sW00T3d7dQs9/7
-NuxCg/A2elmVJSoy8+MLR8JSFEf/aMgjO/TyLg/jAgMBAAGjggGPMIIBizAOBgNV
-HQ8BAf8EBAMCBaAwTQYDVR0gBEYwRDBCBgorBgEEAaAyASgKMDQwMgYIKwYBBQUH
-AgEWJmh0dHBzOi8vd3d3Lmdsb2JhbHNpZ24uY29tL3JlcG9zaXRvcnkvMCQGA1Ud
-EQQdMBuBGXJ5YW4uaHVyc3RAZ2xvYmFsc2lnbi5jb20wCQYDVR0TBAIwADAdBgNV
-HSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwQwYDVR0fBDwwOjA4oDagNIYyaHR0
-cDovL2NybC5nbG9iYWxzaWduLmNvbS9ncy9nc3BlcnNvbmFsc2lnbjJnMi5jcmww
-VQYIKwYBBQUHAQEESTBHMEUGCCsGAQUFBzAChjlodHRwOi8vc2VjdXJlLmdsb2Jh
-bHNpZ24uY29tL2NhY2VydC9nc3BlcnNvbmFsc2lnbjJnMi5jcnQwHQYDVR0OBBYE
-FFWiECe0/L72eVYqcWYnLV6SSjzhMB8GA1UdIwQYMBaAFD8V0m18L+cxnkMKBqiU
-bCw7xe5lMA0GCSqGSIb3DQEBBQUAA4IBAQAhQi6hLPeudmf3IBF4IDzCvRI0FaYd
-BKfprSk/H0PDea4vpsLbWpA0t0SaijiJYtxKjlM4bPd+2chb7ejatDdyrZIzmDVy
-q4c30/xMninGKokpYA11/Ve+i2dvjulu65qasrtQRGybAuuZ67lrp/K3OMFgjV5N
-C3AHYLzvNU4Dwc4QQ1BaMOg6KzYSrKbABRZajfrpC9uiePsv7mDIXLx/toBPxWNl
-a5vJm5DrZdn7uHdvBCE6kMykbOLN5pmEK0UIlwKh6Qi5XD0pzlVkEZliFkBMJgub
-d/eF7xeg7TKPWC5xyOFp9SdMolJM7LTC3wnSO3frBAev+q/nGs9Xxyvs
+MIIIPDCCBiSgAwIBAgIQaMDxFS0pOMxZZeOBxoTJtjANBgkqhkiG9w0BAQsFADCB
+nTELMAkGA1UEBhMCRVMxFDASBgNVBAoMC0laRU5QRSBTLkEuMTowOAYDVQQLDDFB
+WlogWml1cnRhZ2lyaSBwdWJsaWtvYSAtIENlcnRpZmljYWRvIHB1YmxpY28gU0NB
+MTwwOgYDVQQDDDNFQUVrbyBIZXJyaSBBZG1pbmlzdHJhemlvZW4gQ0EgLSBDQSBB
+QVBQIFZhc2NhcyAoMikwHhcNMTcwNzEyMDg1MzIxWhcNMjEwNzEyMDg1MzIxWjCC
+AQwxDzANBgNVBAoMBklaRU5QRTE4MDYGA1UECwwvWml1cnRhZ2lyaSBrb3Jwb3Jh
+dGlib2EtQ2VydGlmaWNhZG8gY29ycG9yYXRpdm8xQzBBBgNVBAsMOkNvbmRpY2lv
+bmVzIGRlIHVzbyBlbiB3d3cuaXplbnBlLmNvbSBub2xhIGVyYWJpbGkgamFraXRl
+a28xFzAVBgNVBC4TDi1kbmkgOTk5OTk5ODlaMSQwIgYDVQQDDBtDT1JQT1JBVElW
+TyBGSUNUSUNJTyBBQ1RJVk8xFDASBgNVBCoMC0NPUlBPUkFUSVZPMREwDwYDVQQE
+DAhGSUNUSUNJTzESMBAGA1UEBRMJOTk5OTk5ODlaMIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEAwVOMwUDfBtsH0XuxYnb+v/L774jMH8valX7RPH8cl2Lb
+SiqSo0RchW2RGA2d1yuYHlpChC9jGmt0X/g66/E/+q2hUJlfJtqVDJFwtFYV4u2S
+yzA3J36V4PRkPQrKxAsbzZriFXAF10XgiHQz9aVeMMJ9GBhmh9+DK8Tm4cMF6i8l
++AuC35KdngPF1x0ealTYrYZplpEJFO7CiW42aLi6vQkDR2R7nmZA4AT69teqBWsK
+0DZ93/f0G/3+vnWwNTBF0lB6dIXoaz8OMSyHLqGnmmAtMrzbjAr/O/WWgbB/BqhR
+qjJQ7Ui16cuDldXaWQ/rkMzsxmsAox0UF+zdQNvXUQIDAQABo4IDBDCCAwAwgccG
+A1UdEgSBvzCBvIYVaHR0cDovL3d3dy5pemVucGUuY29tgQ9pbmZvQGl6ZW5wZS5j
+b22kgZEwgY4xRzBFBgNVBAoMPklaRU5QRSBTLkEuIC0gQ0lGIEEwMTMzNzI2MC1S
+TWVyYy5WaXRvcmlhLUdhc3RlaXogVDEwNTUgRjYyIFM4MUMwQQYDVQQJDDpBdmRh
+IGRlbCBNZWRpdGVycmFuZW8gRXRvcmJpZGVhIDE0IC0gMDEwMTAgVml0b3JpYS1H
+YXN0ZWl6MB4GA1UdEQQXMBWBE2ZpY3RpY2lvQGl6ZW5wZS5ldXMwDgYDVR0PAQH/
+BAQDAgXgMCkGA1UdJQQiMCAGCCsGAQUFBwMCBggrBgEFBQcDBAYKKwYBBAGCNxQC
+AjAdBgNVHQ4EFgQUyeoOD4cgcljKY0JvrNuX2waFQLAwHwYDVR0jBBgwFoAUwKlK
+90clh/+8taaJzoLSRqiJ66MwggEnBgNVHSAEggEeMIIBGjCCARYGCisGAQQB8zkB
+AQEwggEGMDMGCCsGAQUFBwIBFidodHRwOi8vd3d3Lml6ZW5wZS5jb20vcnBhc2Nh
+Y29ycG9yYXRpdm8wgc4GCCsGAQUFBwICMIHBGoG+Wml1cnRhZ2lyaWEgRXVza2Fs
+IEF1dG9ub21pYSBFcmtpZGVnb2tvIHNla3RvcmUgcHVibGlrb2tvIGVyYWt1bmRl
+ZW4gYmFybmUtc2FyZWV0YW4gYmFrYXJyaWsgZXJhYmlsIGRhaXRla2UuIFVzbyBy
+ZXN0cmluZ2lkbyBhbCBhbWJpdG8gZGUgcmVkZXMgaW50ZXJuYXMgZGUgRW50aWRh
+ZGVzIGRlbCBTZWN0b3IgUHVibGljbyBWYXNjbzAyBggrBgEFBQcBAQQmMCQwIgYI
+KwYBBQUHMAGGFmh0dHA6Ly9vY3NwLml6ZW5wZS5jb20wOgYDVR0fBDMwMTAvoC2g
+K4YpaHR0cDovL2NybC5pemVucGUuY29tL2NnaS1iaW4vY3JsaW50ZXJuYTIwDQYJ
+KoZIhvcNAQELBQADggIBAIy5PQ+UZlCRq6ig43vpHwlwuD9daAYeejV0Q+ZbgWAE
+GtO0kT/ytw95ZEJMNiMw3fYfPRlh27ThqiT0VDXZJDlzmn7JZd6QFcdXkCsiuv4+
+ZoXAg/QwnA3SGUUO9aVaXyuOIIuvOfb9MzoGp9xk23SMV3eiLAaLMLqwB5DTfBdt
+BGI7L1MnGJBv8RfP/TL67aJ5bgq2ri4S8vGHtXSjcZ0+rCEOLJtmDNMnTZxancg3
+/H5edeNd+n6Z48LO+JHRxQufbC4mVNxVLMIP9EkGUejlq4E4w6zb5NwCQczJbSWL
+i31rk2orsNsDlyaLGsWZp3JSNX6RmodU4KAUPor4jUJuUhrrm3Spb73gKlV/gcIw
+bCE7mML1Kss3x1ySaXsis6SZtLpGWKkW2iguPWPs0ydV6RPhmsCxieMwPPIJ87vS
+5IejfgyBae7RSuAIHyNFy4uI5xwvwUFf6OZ7az8qtW7ImFOgng3Ds+W9k1S2CNTx
+d0cnKTfA6IpjGo8EeHcxnIXT8NPImWaRj0qqonvYady7ci6U4m3lkNSdXNn1afgw
+mYust+gxVtOZs1gk2MUCgJ1V1X+g7r/Cg7viIn6TLkLrpS1kS1hvMqkl9M+7XqPo
+Qd95nJKOkusQpy99X4dF/lfbYAQnnjnqh3DLD2gvYObXFaAYFaiBKTiMTV2X72F+
 -----END CERTIFICATE-----`
 
 const smimeIntermediate = `-----BEGIN CERTIFICATE-----
-MIIEFjCCAv6gAwIBAgILBAAAAAABL07hL1IwDQYJKoZIhvcNAQEFBQAwVzELMAkG
-A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
-b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw0xMTA0MTMxMDAw
-MDBaFw0xOTA0MTMxMDAwMDBaMFQxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
-YWxTaWduIG52LXNhMSowKAYDVQQDEyFHbG9iYWxTaWduIFBlcnNvbmFsU2lnbiAy
-IENBIC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDBa0H5Nez4
-En3dIlFpX7e5E0YndxQ74xOBbz7kdBd+DLX0LOQMjVPU3DAgKL9ujhH+ZhHkURbH
-3X/94TQSUL/z2JjsaQvS0NqyZXHhM5eeuquzOJRzEQ8+odETzHg2G0Erv7yjSeww
-gkwDWDJnYUDlOjYTDUEG6+i+8Mn425reo4I0E277wD542kmVWeW7+oHv5dZo9e1Q
-yWwiKTEP6BEQVVSBgThXMG4traSSDRUt3T1eQTZx5EObpiBEBO4OTqiBTJfg4vEI
-YgkXzKLpnfszTB6YMDpR9/QS6p3ANB3kfAb+t6udSO3WCst0DGrwHDLBFGDR4UeY
-T5KGGnI7cWL7AgMBAAGjgeUwgeIwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQI
-MAYBAf8CAQAwHQYDVR0OBBYEFD8V0m18L+cxnkMKBqiUbCw7xe5lMEcGA1UdIARA
-MD4wPAYEVR0gADA0MDIGCCsGAQUFBwIBFiZodHRwczovL3d3dy5nbG9iYWxzaWdu
-LmNvbS9yZXBvc2l0b3J5LzAzBgNVHR8ELDAqMCigJqAkhiJodHRwOi8vY3JsLmds
-b2JhbHNpZ24ubmV0L3Jvb3QuY3JsMB8GA1UdIwQYMBaAFGB7ZhpFDZfKiVAvfQTN
-NKj//P1LMA0GCSqGSIb3DQEBBQUAA4IBAQBDc3nMpMxJMQMcYUCB3+C73UpvwDE8
-eCOr7t2F/uaQKKcyqqstqLZc6vPwI/rcE9oDHugY5QEjQzIBIEaTnN6P0vege2IX
-eCOr7t2F/uaQKKcyqqstqLZc6vPwI/rcE9oDHugY5QEjQzIBIEaTnN6P0vege2IX
-YEvTWbWwGdPytDFPYIl3/6OqNSXSnZ7DxPcdLJq2uyiga8PB/TTIIHYkdM2+1DE0
-7y3rH/7TjwDVD7SLu5/SdOfKskuMPTjOEvz3K161mymW06klVhubCIWOro/Gx1Q2
-2FQOZ7/2k4uYoOdBTSlb8kTAuzZNgIE0rB2BIYCTz/P6zZIKW0ogbRSH
+MIIHNzCCBSGgAwIBAgIQJMXIqlZvjuhMvqcFXOFkpDALBgkqhkiG9w0BAQswODEL
+MAkGA1UEBhMCRVMxFDASBgNVBAoMC0laRU5QRSBTLkEuMRMwEQYDVQQDDApJemVu
+cGUuY29tMB4XDTEwMTAyMDA4MjMzM1oXDTM3MTIxMjIzMDAwMFowgZ0xCzAJBgNV
+BAYTAkVTMRQwEgYDVQQKDAtJWkVOUEUgUy5BLjE6MDgGA1UECwwxQVpaIFppdXJ0
+YWdpcmkgcHVibGlrb2EgLSBDZXJ0aWZpY2FkbyBwdWJsaWNvIFNDQTE8MDoGA1UE
+AwwzRUFFa28gSGVycmkgQWRtaW5pc3RyYXppb2VuIENBIC0gQ0EgQUFQUCBWYXNj
+YXMgKDIpMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAoIM7nEdI0N1h
+rR5T4xuV/usKDoMIasaiKvfLhbwxaNtTt+a7W/6wV5bv3svQFIy3sUXjjdzV1nG2
+To2wo/YSPQiOt8exWvOapvL21ogiof+kelWnXFjWaKJI/vThHYLgIYEMj/y4HdtU
+ojI646rZwqsb4YGAopwgmkDfUh5jOhV2IcYE3TgJAYWVkj6jku9PLaIsHiarAHjD
+PY8dig8a4SRv0gm5Yk7FXLmW1d14oxQBDeHZ7zOEXfpafxdEDO2SNaRJjpkh8XRr
+PGqkg2y1Q3gT6b4537jz+StyDIJ3omylmlJsGCwqT7p8mEqjGJ5kC5I2VnjXKuNn
+soShc72khWZVUJiJo5SGuAkNE2ZXqltBVm5Jv6QweQKsX6bkcMc4IZok4a+hx8FM
+8IBpGf/I94pU6HzGXqCyc1d46drJgDY9mXa+6YDAJFl3xeXOOW2iGCfwXqhiCrKL
+MYvyMZzqF3QH5q4nb3ZnehYvraeMFXJXDn+Utqp8vd2r7ShfQJz01KtM4hgKdgSg
+jtW+shkVVN5ng/fPN85ovfAH2BHXFfHmQn4zKsYnLitpwYM/7S1HxlT61cdQ7Nnk
+3LZTYEgAoOmEmdheklT40WAYakksXGM5VrzG7x9S7s1Tm+Vb5LSThdHC8bxxwyTb
+KsDRDNJ84N9fPDO6qHnzaL2upQ43PycCAwEAAaOCAdkwggHVMIHHBgNVHREEgb8w
+gbyGFWh0dHA6Ly93d3cuaXplbnBlLmNvbYEPaW5mb0BpemVucGUuY29tpIGRMIGO
+MUcwRQYDVQQKDD5JWkVOUEUgUy5BLiAtIENJRiBBMDEzMzcyNjAtUk1lcmMuVml0
+b3JpYS1HYXN0ZWl6IFQxMDU1IEY2MiBTODFDMEEGA1UECQw6QXZkYSBkZWwgTWVk
+aXRlcnJhbmVvIEV0b3JiaWRlYSAxNCAtIDAxMDEwIFZpdG9yaWEtR2FzdGVpejAP
+BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUwKlK90cl
+h/+8taaJzoLSRqiJ66MwHwYDVR0jBBgwFoAUHRxlDqjyJXu0kc/ksbHmvVV0bAUw
+OgYDVR0gBDMwMTAvBgRVHSAAMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly93d3cuaXpl
+bnBlLmNvbS9jcHMwNwYIKwYBBQUHAQEEKzApMCcGCCsGAQUFBzABhhtodHRwOi8v
+b2NzcC5pemVucGUuY29tOjgwOTQwMwYDVR0fBCwwKjAooCagJIYiaHR0cDovL2Ny
+bC5pemVucGUuY29tL2NnaS1iaW4vYXJsMjALBgkqhkiG9w0BAQsDggIBAMbjc3HM
+3DG9ubWPkzsF0QsktukpujbTTcGk4h20G7SPRy1DiiTxrRzdAMWGjZioOP3/fKCS
+M539qH0M+gsySNie+iKlbSZJUyE635T1tKw+G7bDUapjlH1xyv55NC5I6wCXGC6E
+3TEP5B/E7dZD0s9E4lS511ubVZivFgOzMYo1DO96diny/N/V1enaTCpRl1qH1OyL
+xUYTijV4ph2gL6exwuG7pxfRcVNHYlrRaXWfTz3F6NBKyULxrI3P/y6JAtN1GqT4
+VF/+vMygx22n0DufGepBwTQz6/rr1ulSZ+eMnuJiTXgh/BzQnkUsXTb8mHII25iR
+0oYF2qAsk6ecWbLiDpkHKIDHmML21MZE13MS8NSvTHoqJO4LyAmDe6SaeNHtrPlK
+b6mzE1BN2ug+ZaX8wLA5IMPFaf0jKhb/Cxu8INsxjt00brsErCc9ip1VNaH0M4bi
+1tGxfiew2436FaeyUxW7Pl6G5GgkNbuUc7QIoRy06DdU/U38BxW3uyJMY60zwHvS
+FlKAn0OvYp4niKhAJwaBVN3kowmJuOU5Rid+TUnfyxbJ9cttSgzaF3hP/N4zgMEM
+5tikXUskeckt8LUK96EH0QyssavAMECUEb/xrupyRdYWwjQGvNLq6T5+fViDGyOw
+k+lzD44wofy8paAy9uC9Owae0zMEzhcsyRm7
+-----END CERTIFICATE-----`
+
+const smimeRoot = `-----BEGIN CERTIFICATE-----
+MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4
+MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6
+ZW5wZS5jb20wHhcNMDcxMjEzMTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYD
+VQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5j
+b20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ03rKDx6sp4boFmVq
+scIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAKClaO
+xdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6H
+LmYRY2xU+zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFX
+uaOKmMPsOzTFlUFpfnXCPCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQD
+yCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxTOTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+
+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbKF7jJeodWLBoBHmy+E60Q
+rLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK0GqfvEyN
+BjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8L
+hij+0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIB
+QFqNeb+Lz0vPqhbBleStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+
+HMh3/1uaD7euBUbl8agW7EekFwIDAQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2lu
+Zm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+SVpFTlBFIFMuQS4gLSBDSUYg
+QTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBGNjIgUzgxQzBB
+BgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx
+MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwHQYDVR0OBBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUA
+A4ICAQB4pgwWSp9MiDrAyw6lFn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWb
+laQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbgakEyrkgPH7UIBzg/YsfqikuFgba56
+awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8qhT/AQKM6WfxZSzwo
+JNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Csg1lw
+LDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCT
+VyvehQP5aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGk
+LhObNA5me0mrZJfQRsN5nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJb
+UjWumDqtujWTI6cfSN01RpiyEGjkpTHCClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/
+QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZoQ0iy2+tzJOeRf1SktoA+
+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1ZWrOZyGls
+QyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw==
 -----END CERTIFICATE-----`
 
 var megaLeaf = `-----BEGIN CERTIFICATE-----
@@ -1315,50 +1374,7 @@
 cw3ESZzThBwWqvPOtJdpXdm+r57pDW8qD+/0lY8wfImMNkQAyCUCLg/1Lxt/hrBj
 -----END CERTIFICATE-----`
 
-const issuerSubjectMatchRoot = `
-Certificate:
-    Data:
-        Version: 3 (0x2)
-        Serial Number: 161640039802297062 (0x23e42c281e55ae6)
-    Signature Algorithm: sha256WithRSAEncryption
-        Issuer: O=Golang, CN=Root ca
-        Validity
-            Not Before: Jan  1 00:00:00 2015 GMT
-            Not After : Jan  1 00:00:00 2025 GMT
-        Subject: O=Golang, CN=Root ca
-        Subject Public Key Info:
-            Public Key Algorithm: rsaEncryption
-                Public-Key: (1024 bit)
-                Modulus:
-                    00:e9:0e:7f:11:0c:e6:5a:e6:86:83:70:f6:51:07:
-                    2e:02:78:11:f5:b2:24:92:38:ee:26:62:02:c7:94:
-                    f1:3e:a1:77:6a:c0:8f:d5:22:68:b6:5d:e2:4c:da:
-                    e0:85:11:35:c2:92:72:49:8d:81:b4:88:97:6b:b7:
-                    fc:b2:44:5b:d9:4d:06:70:f9:0c:c6:8f:e9:b3:df:
-                    a3:6a:84:6c:43:59:be:9d:b2:d0:76:9b:c3:d7:fa:
-                    99:59:c3:b8:e5:f3:53:03:bd:49:d6:b3:cc:a2:43:
-                    fe:ad:c2:0b:b9:01:b8:56:29:94:03:24:a7:0d:28:
-                    21:29:a9:ae:94:5b:4a:f9:9f
-                Exponent: 65537 (0x10001)
-        X509v3 extensions:
-            X509v3 Key Usage: critical
-                Certificate Sign
-            X509v3 Extended Key Usage:
-                TLS Web Server Authentication, TLS Web Client Authentication
-            X509v3 Basic Constraints: critical
-                CA:TRUE
-            X509v3 Subject Key Identifier:
-                40:37:D7:01:FB:40:2F:B8:1C:7E:54:04:27:8C:59:01
-    Signature Algorithm: sha256WithRSAEncryption
-         6f:84:df:49:e0:99:d4:71:66:1d:32:86:56:cb:ea:5a:6b:0e:
-         00:6a:d1:5a:6e:1f:06:23:07:ff:cb:d1:1a:74:e4:24:43:0b:
-         aa:2a:a0:73:75:25:82:bc:bf:3f:a9:f8:48:88:ac:ed:3a:94:
-         3b:0d:d3:88:c8:67:44:61:33:df:71:6c:c5:af:ed:16:8c:bf:
-         82:f9:49:bb:e3:2a:07:53:36:37:25:77:de:91:a4:77:09:7f:
-         6f:b2:91:58:c4:05:89:ea:8e:fa:e1:3b:19:ef:f8:f6:94:b7:
-         7b:27:e6:e4:84:dd:2b:f5:93:f5:3c:d8:86:c5:38:01:56:5c:
-         9f:6d
------BEGIN CERTIFICATE-----
+const issuerSubjectMatchRoot = `-----BEGIN CERTIFICATE-----
 MIICIDCCAYmgAwIBAgIIAj5CwoHlWuYwDQYJKoZIhvcNAQELBQAwIzEPMA0GA1UE
 ChMGR29sYW5nMRAwDgYDVQQDEwdSb290IGNhMB4XDTE1MDEwMTAwMDAwMFoXDTI1
 MDEwMTAwMDAwMFowIzEPMA0GA1UEChMGR29sYW5nMRAwDgYDVQQDEwdSb290IGNh
@@ -1373,53 +1389,7 @@
 eyfm5ITdK/WT9TzYhsU4AVZcn20=
 -----END CERTIFICATE-----`
 
-const issuerSubjectMatchLeaf = `
-Certificate:
-    Data:
-        Version: 3 (0x2)
-        Serial Number: 16785088708916013734 (0xe8f09d3fe25beaa6)
-    Signature Algorithm: sha256WithRSAEncryption
-        Issuer: O=Golang, CN=Root CA
-        Validity
-            Not Before: Jan  1 00:00:00 2015 GMT
-            Not After : Jan  1 00:00:00 2025 GMT
-        Subject: O=Golang, CN=Leaf
-        Subject Public Key Info:
-            Public Key Algorithm: rsaEncryption
-                Public-Key: (1024 bit)
-                Modulus:
-                    00:db:46:7d:93:2e:12:27:06:48:bc:06:28:21:ab:
-                    7e:c4:b6:a2:5d:fe:1e:52:45:88:7a:36:47:a5:08:
-                    0d:92:42:5b:c2:81:c0:be:97:79:98:40:fb:4f:6d:
-                    14:fd:2b:13:8b:c2:a5:2e:67:d8:d4:09:9e:d6:22:
-                    38:b7:4a:0b:74:73:2b:c2:34:f1:d1:93:e5:96:d9:
-                    74:7b:f3:58:9f:6c:61:3c:c0:b0:41:d4:d9:2b:2b:
-                    24:23:77:5b:1c:3b:bd:75:5d:ce:20:54:cf:a1:63:
-                    87:1d:1e:24:c4:f3:1d:1a:50:8b:aa:b6:14:43:ed:
-                    97:a7:75:62:f4:14:c8:52:d7
-                Exponent: 65537 (0x10001)
-        X509v3 extensions:
-            X509v3 Key Usage: critical
-                Digital Signature, Key Encipherment
-            X509v3 Extended Key Usage:
-                TLS Web Server Authentication, TLS Web Client Authentication
-            X509v3 Basic Constraints: critical
-                CA:FALSE
-            X509v3 Subject Key Identifier:
-                9F:91:16:1F:43:43:3E:49:A6:DE:6D:B6:80:D7:9F:60
-            X509v3 Authority Key Identifier:
-                keyid:40:37:D7:01:FB:40:2F:B8:1C:7E:54:04:27:8C:59:01
-
-    Signature Algorithm: sha256WithRSAEncryption
-         8d:86:05:da:89:f5:1d:c5:16:14:41:b9:34:87:2b:5c:38:99:
-         e3:d9:5a:5b:7a:5b:de:0b:5c:08:45:09:6f:1c:9d:31:5f:08:
-         ca:7a:a3:99:da:83:0b:22:be:4f:02:35:91:4e:5d:5c:37:bf:
-         89:22:58:7d:30:76:d2:2f:d0:a0:ee:77:9e:77:c0:d6:19:eb:
-         ec:a0:63:35:6a:80:9b:80:1a:80:de:64:bc:40:38:3c:22:69:
-         ad:46:26:a2:3d:ea:f4:c2:92:49:16:03:96:ae:64:21:b9:7c:
-         ee:64:91:47:81:aa:b4:0c:09:2b:12:1a:b2:f3:af:50:b3:b1:
-         ce:24
------BEGIN CERTIFICATE-----
+const issuerSubjectMatchLeaf = `-----BEGIN CERTIFICATE-----
 MIICODCCAaGgAwIBAgIJAOjwnT/iW+qmMA0GCSqGSIb3DQEBCwUAMCMxDzANBgNV
 BAoTBkdvbGFuZzEQMA4GA1UEAxMHUm9vdCBDQTAeFw0xNTAxMDEwMDAwMDBaFw0y
 NTAxMDEwMDAwMDBaMCAxDzANBgNVBAoTBkdvbGFuZzENMAsGA1UEAxMETGVhZjCB
@@ -1432,11 +1402,9 @@
 hvcNAQELBQADgYEAjYYF2on1HcUWFEG5NIcrXDiZ49laW3pb3gtcCEUJbxydMV8I
 ynqjmdqDCyK+TwI1kU5dXDe/iSJYfTB20i/QoO53nnfA1hnr7KBjNWqAm4AagN5k
 vEA4PCJprUYmoj3q9MKSSRYDlq5kIbl87mSRR4GqtAwJKxIasvOvULOxziQ=
------END CERTIFICATE-----
-`
+-----END CERTIFICATE-----`
 
-const x509v1TestRoot = `
------BEGIN CERTIFICATE-----
+const x509v1TestRoot = `-----BEGIN CERTIFICATE-----
 MIICIDCCAYmgAwIBAgIIAj5CwoHlWuYwDQYJKoZIhvcNAQELBQAwIzEPMA0GA1UE
 ChMGR29sYW5nMRAwDgYDVQQDEwdSb290IENBMB4XDTE1MDEwMTAwMDAwMFoXDTI1
 MDEwMTAwMDAwMFowIzEPMA0GA1UEChMGR29sYW5nMRAwDgYDVQQDEwdSb290IENB
@@ -1451,8 +1419,7 @@
 /1JmacUUofl+HusHuLkDxmadogI=
 -----END CERTIFICATE-----`
 
-const x509v1TestIntermediate = `
------BEGIN CERTIFICATE-----
+const x509v1TestIntermediate = `-----BEGIN CERTIFICATE-----
 MIIByjCCATMCCQCCdEMsT8ykqTANBgkqhkiG9w0BAQsFADAjMQ8wDQYDVQQKEwZH
 b2xhbmcxEDAOBgNVBAMTB1Jvb3QgQ0EwHhcNMTUwMTAxMDAwMDAwWhcNMjUwMTAx
 MDAwMDAwWjAwMQ8wDQYDVQQKEwZHb2xhbmcxHTAbBgNVBAMTFFguNTA5djEgaW50
@@ -1465,8 +1432,7 @@
 x5Wlq1u3YDL/j6s1nU2dQ3ySB/oP7J+vQ9V4QeM+
 -----END CERTIFICATE-----`
 
-const x509v1TestLeaf = `
------BEGIN CERTIFICATE-----
+const x509v1TestLeaf = `-----BEGIN CERTIFICATE-----
 MIICMzCCAZygAwIBAgIJAPo99mqJJrpJMA0GCSqGSIb3DQEBCwUAMDAxDzANBgNV
 BAoTBkdvbGFuZzEdMBsGA1UEAxMUWC41MDl2MSBpbnRlcm1lZGlhdGUwHhcNMTUw
 MTAxMDAwMDAwWhcNMjUwMTAxMDAwMDAwWjArMQ8wDQYDVQQKEwZHb2xhbmcxGDAW
@@ -1481,8 +1447,7 @@
 /jt8qszOXCv2vYdUTPNuPqufXLWMoirpuXrr1liJDmedCcAHepY/
 -----END CERTIFICATE-----`
 
-const ignoreCNWithSANRoot = `
------BEGIN CERTIFICATE-----
+const ignoreCNWithSANRoot = `-----BEGIN CERTIFICATE-----
 MIIDPzCCAiegAwIBAgIIJkzCwkNrPHMwDQYJKoZIhvcNAQELBQAwMDEQMA4GA1UE
 ChMHVEVTVElORzEcMBoGA1UEAxMTKipUZXN0aW5nKiogUm9vdCBDQTAeFw0xNTAx
 MDEwMDAwMDBaFw0yNTAxMDEwMDAwMDBaMDAxEDAOBgNVBAoTB1RFU1RJTkcxHDAa
@@ -1503,8 +1468,7 @@
 BJ6bvwEAasFiLGP6Zbdmxb2hIA==
 -----END CERTIFICATE-----`
 
-const ignoreCNWithSANLeaf = `
------BEGIN CERTIFICATE-----
+const ignoreCNWithSANLeaf = `-----BEGIN CERTIFICATE-----
 MIIDaTCCAlGgAwIBAgIJAONakvRTxgJhMA0GCSqGSIb3DQEBCwUAMDAxEDAOBgNV
 BAoTB1RFU1RJTkcxHDAaBgNVBAMTEyoqVGVzdGluZyoqIFJvb3QgQ0EwHhcNMTUw
 MTAxMDAwMDAwWhcNMjUwMTAxMDAwMDAwWjAsMRAwDgYDVQQKEwdURVNUSU5HMRgw
@@ -1526,8 +1490,7 @@
 xZbqP3Krgjj4XNaXjg==
 -----END CERTIFICATE-----`
 
-const excludedNamesLeaf = `
------BEGIN CERTIFICATE-----
+const excludedNamesLeaf = `-----BEGIN CERTIFICATE-----
 MIID4DCCAsigAwIBAgIHDUSFtJknhzANBgkqhkiG9w0BAQsFADCBnjELMAkGA1UE
 BhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCUxvcyBHYXRvczEU
 MBIGA1UECgwLTmV0ZmxpeCBJbmMxLTArBgNVBAsMJFBsYXRmb3JtIFNlY3VyaXR5
@@ -1549,11 +1512,9 @@
 qKlWE+0S16+pzsWvKn831uylqwIb8ANBPsCX4aM4muFBHavSWAHgRO+P+yXVw8Q+
 VQDnMHUe5PbZd1/+1KKVs1K/CkBCtoHNHp1d/JT+2zUQJphwja9CcgfFdVhSnHL4
 oEEOFtqVMIuQfR2isi08qW/JGOHc4sFoLYB8hvdaxKWSE19A
------END CERTIFICATE-----
-`
+-----END CERTIFICATE-----`
 
-const excludedNamesIntermediate = `
------BEGIN CERTIFICATE-----
+const excludedNamesIntermediate = `-----BEGIN CERTIFICATE-----
 MIIDzTCCArWgAwIBAgIHDUSFqYeczDANBgkqhkiG9w0BAQsFADCBmTELMAkGA1UE
 BhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCUxvcyBHYXRvczEU
 MBIGA1UECgwLTmV0ZmxpeCBJbmMxLTArBgNVBAsMJFBsYXRmb3JtIFNlY3VyaXR5
@@ -1577,8 +1538,7 @@
 zMBX1/lk4wkFckeUIlkD55Y=
 -----END CERTIFICATE-----`
 
-const excludedNamesRoot = `
------BEGIN CERTIFICATE-----
+const excludedNamesRoot = `-----BEGIN CERTIFICATE-----
 MIIEGTCCAwGgAwIBAgIHDUSFpInn/zANBgkqhkiG9w0BAQsFADCBozELMAkGA1UE
 BhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCUxvcyBHYXRvczEU
 MBIGA1UECgwLTmV0ZmxpeCBJbmMxLTArBgNVBAsMJFBsYXRmb3JtIFNlY3VyaXR5
@@ -1603,46 +1563,16 @@
 +NQCZDd5eFeU8PpNX7rgaYE4GPq+EEmLVCBYmdctr8QVdqJ//8Xu3+1phjDy
 -----END CERTIFICATE-----`
 
-const invalidCNRoot = `
------BEGIN CERTIFICATE-----
+const invalidCNRoot = `-----BEGIN CERTIFICATE-----
 MIIBFjCBvgIJAIsu4r+jb70UMAoGCCqGSM49BAMCMBQxEjAQBgNVBAsMCVRlc3Qg
 cm9vdDAeFw0xODA3MTExODMyMzVaFw0yODA3MDgxODMyMzVaMBQxEjAQBgNVBAsM
 CVRlc3Qgcm9vdDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABF6oDgMg0LV6YhPj
 QXaPXYCc2cIyCdqp0ROUksRz0pOLTc5iY2nraUheRUD1vRRneq7GeXOVNn7uXONg
 oCGMjNwwCgYIKoZIzj0EAwIDRwAwRAIgDSiwgIn8g1lpruYH0QD1GYeoWVunfmrI
 XzZZl0eW/ugCICgOfXeZ2GGy3wIC0352BaC3a8r5AAb2XSGNe+e9wNN6
------END CERTIFICATE-----
-`
+-----END CERTIFICATE-----`
 
-const invalidCNWithoutSAN = `
-Certificate:
-    Data:
-        Version: 1 (0x0)
-        Serial Number:
-            07:ba:bc:b7:d9:ab:0c:02:fe:50:1d:4e:15:a3:0d:e4:11:16:14:a2
-        Signature Algorithm: ecdsa-with-SHA256
-        Issuer: OU = Test root
-        Validity
-            Not Before: Jul 11 18:35:21 2018 GMT
-            Not After : Jul  8 18:35:21 2028 GMT
-        Subject: CN = "foo,invalid"
-        Subject Public Key Info:
-            Public Key Algorithm: id-ecPublicKey
-                Public-Key: (256 bit)
-                pub:
-                    04:a7:a6:7c:22:33:a7:47:7f:08:93:2d:5f:61:35:
-                    2e:da:45:67:76:f2:97:73:18:b0:01:12:4a:1a:d5:
-                    b7:6f:41:3c:bb:05:69:f4:06:5d:ff:eb:2b:a7:85:
-                    0b:4c:f7:45:4e:81:40:7a:a9:c6:1d:bb:ba:d9:b9:
-                    26:b3:ca:50:90
-                ASN1 OID: prime256v1
-                NIST CURVE: P-256
-    Signature Algorithm: ecdsa-with-SHA256
-         30:45:02:21:00:85:96:75:b6:72:3c:67:12:a0:7f:86:04:81:
-         d2:dd:c8:67:50:d7:5f:85:c0:54:54:fc:e6:6b:45:08:93:d3:
-         2a:02:20:60:86:3e:d6:28:a6:4e:da:dd:6e:95:89:cc:00:76:
-         78:1c:03:80:85:a6:5a:0b:eb:c5:f3:9c:2e:df:ef:6e:fa
------BEGIN CERTIFICATE-----
+const invalidCNWithoutSAN = `-----BEGIN CERTIFICATE-----
 MIIBJDCBywIUB7q8t9mrDAL+UB1OFaMN5BEWFKIwCgYIKoZIzj0EAwIwFDESMBAG
 A1UECwwJVGVzdCByb290MB4XDTE4MDcxMTE4MzUyMVoXDTI4MDcwODE4MzUyMVow
 FjEUMBIGA1UEAwwLZm9vLGludmFsaWQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC
@@ -1650,38 +1580,9 @@
 90VOgUB6qcYdu7rZuSazylCQMAoGCCqGSM49BAMCA0gAMEUCIQCFlnW2cjxnEqB/
 hgSB0t3IZ1DXX4XAVFT85mtFCJPTKgIgYIY+1iimTtrdbpWJzAB2eBwDgIWmWgvr
 xfOcLt/vbvo=
------END CERTIFICATE-----
-`
+-----END CERTIFICATE-----`
 
-const validCNWithoutSAN = `
-Certificate:
-    Data:
-        Version: 1 (0x0)
-        Serial Number:
-            07:ba:bc:b7:d9:ab:0c:02:fe:50:1d:4e:15:a3:0d:e4:11:16:14:a4
-        Signature Algorithm: ecdsa-with-SHA256
-        Issuer: OU = Test root
-        Validity
-            Not Before: Jul 11 18:47:24 2018 GMT
-            Not After : Jul  8 18:47:24 2028 GMT
-        Subject: CN = foo.example.com
-        Subject Public Key Info:
-            Public Key Algorithm: id-ecPublicKey
-                Public-Key: (256 bit)
-                pub:
-                    04:a7:a6:7c:22:33:a7:47:7f:08:93:2d:5f:61:35:
-                    2e:da:45:67:76:f2:97:73:18:b0:01:12:4a:1a:d5:
-                    b7:6f:41:3c:bb:05:69:f4:06:5d:ff:eb:2b:a7:85:
-                    0b:4c:f7:45:4e:81:40:7a:a9:c6:1d:bb:ba:d9:b9:
-                    26:b3:ca:50:90
-                ASN1 OID: prime256v1
-                NIST CURVE: P-256
-    Signature Algorithm: ecdsa-with-SHA256
-         30:44:02:20:53:6c:d7:b7:59:61:51:72:a5:18:a3:4b:0d:52:
-         ea:15:fa:d0:93:30:32:54:4b:ed:0f:58:85:b8:a8:1a:82:3b:
-         02:20:14:77:4b:0e:7e:4f:0a:4f:64:26:97:dc:d0:ed:aa:67:
-         1d:37:85:da:b4:87:ba:25:1c:2a:58:f7:23:11:8b:3d
------BEGIN CERTIFICATE-----
+const validCNWithoutSAN = `-----BEGIN CERTIFICATE-----
 MIIBJzCBzwIUB7q8t9mrDAL+UB1OFaMN5BEWFKQwCgYIKoZIzj0EAwIwFDESMBAG
 A1UECwwJVGVzdCByb290MB4XDTE4MDcxMTE4NDcyNFoXDTI4MDcwODE4NDcyNFow
 GjEYMBYGA1UEAwwPZm9vLmV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0D
@@ -1689,48 +1590,9 @@
 p4ULTPdFToFAeqnGHbu62bkms8pQkDAKBggqhkjOPQQDAgNHADBEAiBTbNe3WWFR
 cqUYo0sNUuoV+tCTMDJUS+0PWIW4qBqCOwIgFHdLDn5PCk9kJpfc0O2qZx03hdq0
 h7olHCpY9yMRiz0=
------END CERTIFICATE-----
-`
+-----END CERTIFICATE-----`
 
-const (
-	rootWithoutSKID = `
-Certificate:
-    Data:
-        Version: 3 (0x2)
-        Serial Number:
-            78:29:2a:dc:2f:12:39:7f:c9:33:93:ea:61:39:7d:70
-        Signature Algorithm: ecdsa-with-SHA256
-        Issuer: O = Acme Co
-        Validity
-            Not Before: Feb  4 22:56:34 2019 GMT
-            Not After : Feb  1 22:56:34 2029 GMT
-        Subject: O = Acme Co
-        Subject Public Key Info:
-            Public Key Algorithm: id-ecPublicKey
-                Public-Key: (256 bit)
-                pub:
-                    04:84:a6:8c:69:53:af:87:4b:39:64:fe:04:24:e6:
-                    d8:fc:d6:46:39:35:0e:92:dc:48:08:7e:02:5f:1e:
-                    07:53:5c:d9:e0:56:c5:82:07:f6:a3:e2:ad:f6:ad:
-                    be:a0:4e:03:87:39:67:0c:9c:46:91:68:6b:0e:8e:
-                    f8:49:97:9d:5b
-                ASN1 OID: prime256v1
-                NIST CURVE: P-256
-        X509v3 extensions:
-            X509v3 Key Usage: critical
-                Digital Signature, Key Encipherment, Certificate Sign
-            X509v3 Extended Key Usage:
-                TLS Web Server Authentication
-            X509v3 Basic Constraints: critical
-                CA:TRUE
-            X509v3 Subject Alternative Name:
-                DNS:example
-    Signature Algorithm: ecdsa-with-SHA256
-         30:46:02:21:00:c6:81:61:61:42:8d:37:e7:d0:c3:72:43:44:
-         17:bd:84:ff:88:81:68:9a:99:08:ab:3c:3a:c0:1e:ea:8c:ba:
-         c0:02:21:00:de:c9:fa:e5:5e:c6:e2:db:23:64:43:a9:37:42:
-         72:92:7f:6e:89:38:ea:9e:2a:a7:fd:2f:ea:9a:ff:20:21:e7
------BEGIN CERTIFICATE-----
+const rootWithoutSKID = `-----BEGIN CERTIFICATE-----
 MIIBbzCCARSgAwIBAgIQeCkq3C8SOX/JM5PqYTl9cDAKBggqhkjOPQQDAjASMRAw
 DgYDVQQKEwdBY21lIENvMB4XDTE5MDIwNDIyNTYzNFoXDTI5MDIwMTIyNTYzNFow
 EjEQMA4GA1UEChMHQWNtZSBDbzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABISm
@@ -1739,49 +1601,9 @@
 BgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MBIGA1UdEQQLMAmCB2V4YW1wbGUwCgYI
 KoZIzj0EAwIDSQAwRgIhAMaBYWFCjTfn0MNyQ0QXvYT/iIFompkIqzw6wB7qjLrA
 AiEA3sn65V7G4tsjZEOpN0Jykn9uiTjqniqn/S/qmv8gIec=
------END CERTIFICATE-----
-`
-	leafWithAKID = `
-	Certificate:
-    Data:
-        Version: 3 (0x2)
-        Serial Number:
-            f0:8a:62:f0:03:84:a2:cf:69:63:ad:71:3b:b6:5d:8c
-        Signature Algorithm: ecdsa-with-SHA256
-        Issuer: O = Acme Co
-        Validity
-            Not Before: Feb  4 23:06:52 2019 GMT
-            Not After : Feb  1 23:06:52 2029 GMT
-        Subject: O = Acme LLC
-        Subject Public Key Info:
-            Public Key Algorithm: id-ecPublicKey
-                Public-Key: (256 bit)
-                pub:
-                    04:5a:4e:4d:fb:ff:17:f7:b6:13:e8:29:45:34:81:
-                    39:ff:8c:9c:d9:8c:0a:9f:dd:b5:97:4c:2b:20:91:
-                    1c:4f:6b:be:53:27:66:ec:4a:ad:08:93:6d:66:36:
-                    0c:02:70:5d:01:ca:7f:c3:29:e9:4f:00:ba:b4:14:
-                    ec:c5:c3:34:b3
-                ASN1 OID: prime256v1
-                NIST CURVE: P-256
-        X509v3 extensions:
-            X509v3 Key Usage: critical
-                Digital Signature, Key Encipherment
-            X509v3 Extended Key Usage:
-                TLS Web Server Authentication
-            X509v3 Basic Constraints: critical
-                CA:FALSE
-            X509v3 Authority Key Identifier:
-                keyid:C2:2B:5F:91:78:34:26:09:42:8D:6F:51:B2:C5:AF:4C:0B:DE:6A:42
+-----END CERTIFICATE-----`
 
-            X509v3 Subject Alternative Name:
-                DNS:example
-    Signature Algorithm: ecdsa-with-SHA256
-         30:44:02:20:64:e0:ba:56:89:63:ce:22:5e:4f:22:15:fd:3c:
-         35:64:9a:3a:6b:7b:9a:32:a0:7f:f7:69:8c:06:f0:00:58:b8:
-         02:20:09:e4:9f:6d:8b:9e:38:e1:b6:01:d5:ee:32:a4:94:65:
-         93:2a:78:94:bb:26:57:4b:c7:dd:6c:3d:40:2b:63:90
------BEGIN CERTIFICATE-----
+const leafWithAKID = `-----BEGIN CERTIFICATE-----
 MIIBjTCCATSgAwIBAgIRAPCKYvADhKLPaWOtcTu2XYwwCgYIKoZIzj0EAwIwEjEQ
 MA4GA1UEChMHQWNtZSBDbzAeFw0xOTAyMDQyMzA2NTJaFw0yOTAyMDEyMzA2NTJa
 MBMxETAPBgNVBAoTCEFjbWUgTExDMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE
@@ -1791,9 +1613,7 @@
 ssWvTAveakIwEgYDVR0RBAswCYIHZXhhbXBsZTAKBggqhkjOPQQDAgNHADBEAiBk
 4LpWiWPOIl5PIhX9PDVkmjpre5oyoH/3aYwG8ABYuAIgCeSfbYueOOG2AdXuMqSU
 ZZMqeJS7JldLx91sPUArY5A=
------END CERTIFICATE-----
-`
-)
+-----END CERTIFICATE-----`
 
 var unknownAuthorityErrorTests = []struct {
 	cert     string
@@ -2124,3 +1944,33 @@
 	}
 	t.Logf("verification took %v", time.Since(start))
 }
+
+func TestSystemRootsError(t *testing.T) {
+	if runtime.GOOS == "windows" {
+		t.Skip("Windows does not use (or support) systemRoots")
+	}
+
+	defer func(oldSystemRoots *CertPool) { systemRoots = oldSystemRoots }(systemRootsPool())
+
+	opts := VerifyOptions{
+		Intermediates: NewCertPool(),
+		DNSName:       "www.google.com",
+		CurrentTime:   time.Unix(1395785200, 0),
+	}
+
+	if ok := opts.Intermediates.AppendCertsFromPEM([]byte(giag2Intermediate)); !ok {
+		t.Fatalf("failed to parse intermediate")
+	}
+
+	leaf, err := certificateFromPEM(googleLeaf)
+	if err != nil {
+		t.Fatalf("failed to parse leaf: %v", err)
+	}
+
+	systemRoots = nil
+
+	_, err = leaf.Verify(opts)
+	if _, ok := err.(SystemRootsError); !ok {
+		t.Errorf("error was not SystemRootsError: %v", err)
+	}
+}
diff --git a/libgo/go/database/sql/driver/driver.go b/libgo/go/database/sql/driver/driver.go
index 316e7ce..a0ba7ec 100644
--- a/libgo/go/database/sql/driver/driver.go
+++ b/libgo/go/database/sql/driver/driver.go
@@ -255,12 +255,9 @@
 // SessionResetter may be implemented by Conn to allow drivers to reset the
 // session state associated with the connection and to signal a bad connection.
 type SessionResetter interface {
-	// ResetSession is called while a connection is in the connection
-	// pool. No queries will run on this connection until this method returns.
-	//
-	// If the connection is bad this should return driver.ErrBadConn to prevent
-	// the connection from being returned to the connection pool. Any other
-	// error will be discarded.
+	// ResetSession is called prior to executing a query on the connection
+	// if the connection has been used before. If the driver returns ErrBadConn
+	// the connection is discarded.
 	ResetSession(ctx context.Context) error
 }
 
diff --git a/libgo/go/database/sql/fakedb_test.go b/libgo/go/database/sql/fakedb_test.go
index a0028be..0ec72d4 100644
--- a/libgo/go/database/sql/fakedb_test.go
+++ b/libgo/go/database/sql/fakedb_test.go
@@ -390,12 +390,19 @@
 
 func (c *fakeConn) ResetSession(ctx context.Context) error {
 	c.dirtySession = false
+	c.currTx = nil
 	if c.isBad() {
 		return driver.ErrBadConn
 	}
 	return nil
 }
 
+var _ validator = (*fakeConn)(nil)
+
+func (c *fakeConn) IsValid() bool {
+	return !c.isBad()
+}
+
 func (c *fakeConn) Close() (err error) {
 	drv := fdriver.(*fakeDriver)
 	defer func() {
@@ -728,6 +735,9 @@
 func (s *fakeStmt) Exec(args []driver.Value) (driver.Result, error) {
 	panic("Using ExecContext")
 }
+
+var errFakeConnSessionDirty = errors.New("fakedb: session is dirty")
+
 func (s *fakeStmt) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error) {
 	if s.panic == "Exec" {
 		panic(s.panic)
@@ -740,7 +750,7 @@
 		return nil, driver.ErrBadConn
 	}
 	if s.c.isDirtyAndMark() {
-		return nil, errors.New("fakedb: session is dirty")
+		return nil, errFakeConnSessionDirty
 	}
 
 	err := checkSubsetTypes(s.c.db.allowAny, args)
@@ -854,7 +864,7 @@
 		return nil, driver.ErrBadConn
 	}
 	if s.c.isDirtyAndMark() {
-		return nil, errors.New("fakedb: session is dirty")
+		return nil, errFakeConnSessionDirty
 	}
 
 	err := checkSubsetTypes(s.c.db.allowAny, args)
@@ -887,6 +897,37 @@
 				}
 			}
 		}
+		if s.table == "tx_status" && s.colName[0] == "tx_status" {
+			txStatus := "autocommit"
+			if s.c.currTx != nil {
+				txStatus = "transaction"
+			}
+			cursor := &rowsCursor{
+				parentMem: s.c,
+				posRow:    -1,
+				rows: [][]*row{
+					[]*row{
+						{
+							cols: []interface{}{
+								txStatus,
+							},
+						},
+					},
+				},
+				cols: [][]string{
+					[]string{
+						"tx_status",
+					},
+				},
+				colType: [][]string{
+					[]string{
+						"string",
+					},
+				},
+				errPos: -1,
+			}
+			return cursor, nil
+		}
 
 		t.mu.Lock()
 
diff --git a/libgo/go/database/sql/sql.go b/libgo/go/database/sql/sql.go
index 0f5bbc0..a0b7ca8 100644
--- a/libgo/go/database/sql/sql.go
+++ b/libgo/go/database/sql/sql.go
@@ -421,7 +421,6 @@
 	// It is closed during db.Close(). The close tells the connectionOpener
 	// goroutine to exit.
 	openerCh          chan struct{}
-	resetterCh        chan *driverConn
 	closed            bool
 	dep               map[finalCloser]depSet
 	lastPut           map[*driverConn]string // stacktrace of last conn's put; debug only
@@ -458,10 +457,10 @@
 
 	sync.Mutex  // guards following
 	ci          driver.Conn
+	needReset   bool // The connection session should be reset before use if true.
 	closed      bool
 	finalClosed bool // ci.Close has been called
 	openStmt    map[*driverStmt]bool
-	lastErr     error // lastError captures the result of the session resetter.
 
 	// guarded by db.mu
 	inUse      bool
@@ -486,6 +485,41 @@
 	return dc.createdAt.Add(timeout).Before(nowFunc())
 }
 
+// resetSession checks if the driver connection needs the
+// session to be reset and if required, resets it.
+func (dc *driverConn) resetSession(ctx context.Context) error {
+	dc.Lock()
+	defer dc.Unlock()
+
+	if !dc.needReset {
+		return nil
+	}
+	if cr, ok := dc.ci.(driver.SessionResetter); ok {
+		return cr.ResetSession(ctx)
+	}
+	return nil
+}
+
+// validator was introduced for Go1.15, but backported to Go1.14.
+type validator interface {
+	IsValid() bool
+}
+
+// validateConnection checks if the connection is valid and can
+// still be used. It also marks the session for reset if required.
+func (dc *driverConn) validateConnection(needsReset bool) bool {
+	dc.Lock()
+	defer dc.Unlock()
+
+	if needsReset {
+		dc.needReset = true
+	}
+	if cv, ok := dc.ci.(validator); ok {
+		return cv.IsValid()
+	}
+	return true
+}
+
 // prepareLocked prepares the query on dc. When cg == nil the dc must keep track of
 // the prepared statements in a pool.
 func (dc *driverConn) prepareLocked(ctx context.Context, cg stmtConnGrabber, query string) (*driverStmt, error) {
@@ -511,19 +545,6 @@
 	return ds, nil
 }
 
-// resetSession resets the connection session and sets the lastErr
-// that is checked before returning the connection to another query.
-//
-// resetSession assumes that the embedded mutex is locked when the connection
-// was returned to the pool. This unlocks the mutex.
-func (dc *driverConn) resetSession(ctx context.Context) {
-	defer dc.Unlock() // In case of panic.
-	if dc.closed {    // Check if the database has been closed.
-		return
-	}
-	dc.lastErr = dc.ci.(driver.SessionResetter).ResetSession(ctx)
-}
-
 // the dc.db's Mutex is held.
 func (dc *driverConn) closeDBLocked() func() error {
 	dc.Lock()
@@ -713,14 +734,12 @@
 	db := &DB{
 		connector:    c,
 		openerCh:     make(chan struct{}, connectionRequestQueueSize),
-		resetterCh:   make(chan *driverConn, 50),
 		lastPut:      make(map[*driverConn]string),
 		connRequests: make(map[uint64]chan connRequest),
 		stop:         cancel,
 	}
 
 	go db.connectionOpener(ctx)
-	go db.connectionResetter(ctx)
 
 	return db
 }
@@ -1058,23 +1077,6 @@
 	}
 }
 
-// connectionResetter runs in a separate goroutine to reset connections async
-// to exported API.
-func (db *DB) connectionResetter(ctx context.Context) {
-	for {
-		select {
-		case <-ctx.Done():
-			close(db.resetterCh)
-			for dc := range db.resetterCh {
-				dc.Unlock()
-			}
-			return
-		case dc := <-db.resetterCh:
-			dc.resetSession(ctx)
-		}
-	}
-}
-
 // Open one new connection
 func (db *DB) openNewConnection(ctx context.Context) {
 	// maybeOpenNewConnctions has already executed db.numOpen++ before it sent
@@ -1155,14 +1157,13 @@
 			conn.Close()
 			return nil, driver.ErrBadConn
 		}
-		// Lock around reading lastErr to ensure the session resetter finished.
-		conn.Lock()
-		err := conn.lastErr
-		conn.Unlock()
-		if err == driver.ErrBadConn {
+
+		// Reset the session if required.
+		if err := conn.resetSession(ctx); err == driver.ErrBadConn {
 			conn.Close()
 			return nil, driver.ErrBadConn
 		}
+
 		return conn, nil
 	}
 
@@ -1204,18 +1205,22 @@
 			if !ok {
 				return nil, errDBClosed
 			}
-			if ret.err == nil && ret.conn.expired(lifetime) {
+			// Only check if the connection is expired if the strategy is cachedOrNewConns.
+			// If we require a new connection, just re-use the connection without looking
+			// at the expiry time. If it is expired, it will be checked when it is placed
+			// back into the connection pool.
+			// This prioritizes giving a valid connection to a client over the exact connection
+			// lifetime, which could expire exactly after this point anyway.
+			if strategy == cachedOrNewConn && ret.err == nil && ret.conn.expired(lifetime) {
 				ret.conn.Close()
 				return nil, driver.ErrBadConn
 			}
 			if ret.conn == nil {
 				return nil, ret.err
 			}
-			// Lock around reading lastErr to ensure the session resetter finished.
-			ret.conn.Lock()
-			err := ret.conn.lastErr
-			ret.conn.Unlock()
-			if err == driver.ErrBadConn {
+
+			// Reset the session if required.
+			if err := ret.conn.resetSession(ctx); err == driver.ErrBadConn {
 				ret.conn.Close()
 				return nil, driver.ErrBadConn
 			}
@@ -1275,13 +1280,23 @@
 // putConn adds a connection to the db's free pool.
 // err is optionally the last error that occurred on this connection.
 func (db *DB) putConn(dc *driverConn, err error, resetSession bool) {
+	if err != driver.ErrBadConn {
+		if !dc.validateConnection(resetSession) {
+			err = driver.ErrBadConn
+		}
+	}
 	db.mu.Lock()
 	if !dc.inUse {
+		db.mu.Unlock()
 		if debugGetPut {
 			fmt.Printf("putConn(%v) DUPLICATE was: %s\n\nPREVIOUS was: %s", dc, stack(), db.lastPut[dc])
 		}
 		panic("sql: connection returned that was never out")
 	}
+
+	if err != driver.ErrBadConn && dc.expired(db.maxLifetime) {
+		err = driver.ErrBadConn
+	}
 	if debugGetPut {
 		db.lastPut[dc] = stack()
 	}
@@ -1305,41 +1320,13 @@
 	if putConnHook != nil {
 		putConnHook(db, dc)
 	}
-	if db.closed {
-		// Connections do not need to be reset if they will be closed.
-		// Prevents writing to resetterCh after the DB has closed.
-		resetSession = false
-	}
-	if resetSession {
-		if _, resetSession = dc.ci.(driver.SessionResetter); resetSession {
-			// Lock the driverConn here so it isn't released until
-			// the connection is reset.
-			// The lock must be taken before the connection is put into
-			// the pool to prevent it from being taken out before it is reset.
-			dc.Lock()
-		}
-	}
 	added := db.putConnDBLocked(dc, nil)
 	db.mu.Unlock()
 
 	if !added {
-		if resetSession {
-			dc.Unlock()
-		}
 		dc.Close()
 		return
 	}
-	if !resetSession {
-		return
-	}
-	select {
-	default:
-		// If the resetterCh is blocking then mark the connection
-		// as bad and continue on.
-		dc.lastErr = driver.ErrBadConn
-		dc.Unlock()
-	case db.resetterCh <- dc:
-	}
 }
 
 // Satisfy a connRequest or put the driverConn in the idle pool and return true
@@ -1701,7 +1688,11 @@
 // beginDC starts a transaction. The provided dc must be valid and ready to use.
 func (db *DB) beginDC(ctx context.Context, dc *driverConn, release func(error), opts *TxOptions) (tx *Tx, err error) {
 	var txi driver.Tx
+	keepConnOnRollback := false
 	withLock(dc, func() {
+		_, hasSessionResetter := dc.ci.(driver.SessionResetter)
+		_, hasConnectionValidator := dc.ci.(validator)
+		keepConnOnRollback = hasSessionResetter && hasConnectionValidator
 		txi, err = ctxDriverBegin(ctx, opts, dc.ci)
 	})
 	if err != nil {
@@ -1713,12 +1704,13 @@
 	// The cancel function in Tx will be called after done is set to true.
 	ctx, cancel := context.WithCancel(ctx)
 	tx = &Tx{
-		db:          db,
-		dc:          dc,
-		releaseConn: release,
-		txi:         txi,
-		cancel:      cancel,
-		ctx:         ctx,
+		db:                 db,
+		dc:                 dc,
+		releaseConn:        release,
+		txi:                txi,
+		cancel:             cancel,
+		keepConnOnRollback: keepConnOnRollback,
+		ctx:                ctx,
 	}
 	go tx.awaitDone()
 	return tx, nil
@@ -1980,6 +1972,11 @@
 	// Use atomic operations on value when checking value.
 	done int32
 
+	// keepConnOnRollback is true if the driver knows
+	// how to reset the connection's session and if need be discard
+	// the connection.
+	keepConnOnRollback bool
+
 	// All Stmts prepared for this transaction. These will be closed after the
 	// transaction has been committed or rolled back.
 	stmts struct {
@@ -2005,7 +2002,10 @@
 	// transaction is closed and the resources are released.  This
 	// rollback does nothing if the transaction has already been
 	// committed or rolled back.
-	tx.rollback(true)
+	// Do not discard the connection if the connection knows
+	// how to reset the session.
+	discardConnection := !tx.keepConnOnRollback
+	tx.rollback(discardConnection)
 }
 
 func (tx *Tx) isDone() bool {
@@ -2016,14 +2016,10 @@
 // that has already been committed or rolled back.
 var ErrTxDone = errors.New("sql: transaction has already been committed or rolled back")
 
-// close returns the connection to the pool and
-// must only be called by Tx.rollback or Tx.Commit.
-func (tx *Tx) close(err error) {
-	tx.cancel()
-
-	tx.closemu.Lock()
-	defer tx.closemu.Unlock()
-
+// closeLocked returns the connection to the pool and
+// must only be called by Tx.rollback or Tx.Commit while
+// closemu is Locked and tx already canceled.
+func (tx *Tx) closeLocked(err error) {
 	tx.releaseConn(err)
 	tx.dc = nil
 	tx.txi = nil
@@ -2090,6 +2086,15 @@
 	if !atomic.CompareAndSwapInt32(&tx.done, 0, 1) {
 		return ErrTxDone
 	}
+
+	// Cancel the Tx to release any active R-closemu locks.
+	// This is safe to do because tx.done has already transitioned
+	// from 0 to 1. Hold the W-closemu lock prior to rollback
+	// to ensure no other connection has an active query.
+	tx.cancel()
+	tx.closemu.Lock()
+	defer tx.closemu.Unlock()
+
 	var err error
 	withLock(tx.dc, func() {
 		err = tx.txi.Commit()
@@ -2097,16 +2102,31 @@
 	if err != driver.ErrBadConn {
 		tx.closePrepared()
 	}
-	tx.close(err)
+	tx.closeLocked(err)
 	return err
 }
 
+var rollbackHook func()
+
 // rollback aborts the transaction and optionally forces the pool to discard
 // the connection.
 func (tx *Tx) rollback(discardConn bool) error {
 	if !atomic.CompareAndSwapInt32(&tx.done, 0, 1) {
 		return ErrTxDone
 	}
+
+	if rollbackHook != nil {
+		rollbackHook()
+	}
+
+	// Cancel the Tx to release any active R-closemu locks.
+	// This is safe to do because tx.done has already transitioned
+	// from 0 to 1. Hold the W-closemu lock prior to rollback
+	// to ensure no other connection has an active query.
+	tx.cancel()
+	tx.closemu.Lock()
+	defer tx.closemu.Unlock()
+
 	var err error
 	withLock(tx.dc, func() {
 		err = tx.txi.Rollback()
@@ -2117,7 +2137,7 @@
 	if discardConn {
 		err = driver.ErrBadConn
 	}
-	tx.close(err)
+	tx.closeLocked(err)
 	return err
 }
 
diff --git a/libgo/go/database/sql/sql_test.go b/libgo/go/database/sql/sql_test.go
index 6f59260..a9e1800 100644
--- a/libgo/go/database/sql/sql_test.go
+++ b/libgo/go/database/sql/sql_test.go
@@ -80,6 +80,11 @@
 		exec(t, db, "CREATE|magicquery|op=string,millis=int32")
 		exec(t, db, "INSERT|magicquery|op=sleep,millis=10")
 	}
+	if name == "tx_status" {
+		// Magic table name and column, known by fakedb_test.go.
+		exec(t, db, "CREATE|tx_status|tx_status=string")
+		exec(t, db, "INSERT|tx_status|tx_status=invalid")
+	}
 	return db
 }
 
@@ -437,6 +442,7 @@
 		}
 		t.Fatal(err)
 	}
+	tx.keepConnOnRollback = false
 
 	// This will trigger the *fakeConn.Prepare method which will take time
 	// performing the query. The ctxDriverPrepare func will check the context
@@ -449,6 +455,35 @@
 	waitForFree(t, db, 5*time.Second, 0)
 }
 
+// TestTxContextWaitNoDiscard is the same as TestTxContextWait, but should not discard
+// the final connection.
+func TestTxContextWaitNoDiscard(t *testing.T) {
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+
+	ctx, cancel := context.WithTimeout(context.Background(), 15*time.Millisecond)
+	defer cancel()
+
+	tx, err := db.BeginTx(ctx, nil)
+	if err != nil {
+		// Guard against the context being canceled before BeginTx completes.
+		if err == context.DeadlineExceeded {
+			t.Skip("tx context canceled prior to first use")
+		}
+		t.Fatal(err)
+	}
+
+	// This will trigger the *fakeConn.Prepare method which will take time
+	// performing the query. The ctxDriverPrepare func will check the context
+	// after this and close the rows and return an error.
+	_, err = tx.QueryContext(ctx, "WAIT|1s|SELECT|people|age,name|")
+	if err != context.DeadlineExceeded {
+		t.Fatalf("expected QueryContext to error with context deadline exceeded but returned %v", err)
+	}
+
+	waitForFree(t, db, 5*time.Second, 1)
+}
+
 // TestUnsupportedOptions checks that the database fails when a driver that
 // doesn't implement ConnBeginTx is used with non-default options and an
 // un-cancellable context.
@@ -1525,6 +1560,37 @@
 	}
 }
 
+// TestConnIsValid verifies that a database connection that should be discarded,
+// is actually discarded and does not re-enter the connection pool.
+// If the IsValid method from *fakeConn is removed, this test will fail.
+func TestConnIsValid(t *testing.T) {
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+
+	db.SetMaxOpenConns(1)
+
+	ctx := context.Background()
+
+	c, err := db.Conn(ctx)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	err = c.Raw(func(raw interface{}) error {
+		dc := raw.(*fakeConn)
+		dc.stickyBad = true
+		return nil
+	})
+	if err != nil {
+		t.Fatal(err)
+	}
+	c.Close()
+
+	if len(db.freeConn) > 0 && db.freeConn[0].ci.(*fakeConn).stickyBad {
+		t.Fatal("bad connection returned to pool; expected bad connection to be discarded")
+	}
+}
+
 // Tests fix for issue 2542, that we release a lock when querying on
 // a closed connection.
 func TestIssue2542Deadlock(t *testing.T) {
@@ -2658,6 +2724,159 @@
 	}
 }
 
+// Issue 34755: Ensure that a Tx cannot commit after a rollback.
+func TestTxCannotCommitAfterRollback(t *testing.T) {
+	db := newTestDB(t, "tx_status")
+	defer closeDB(t, db)
+
+	// First check query reporting is correct.
+	var txStatus string
+	err := db.QueryRow("SELECT|tx_status|tx_status|").Scan(&txStatus)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if g, w := txStatus, "autocommit"; g != w {
+		t.Fatalf("tx_status=%q, wanted %q", g, w)
+	}
+
+	ctx, cancel := context.WithCancel(context.Background())
+	defer cancel()
+
+	tx, err := db.BeginTx(ctx, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// Ignore dirty session for this test.
+	// A failing test should trigger the dirty session flag as well,
+	// but that isn't exactly what this should test for.
+	tx.txi.(*fakeTx).c.skipDirtySession = true
+
+	defer tx.Rollback()
+
+	err = tx.QueryRow("SELECT|tx_status|tx_status|").Scan(&txStatus)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if g, w := txStatus, "transaction"; g != w {
+		t.Fatalf("tx_status=%q, wanted %q", g, w)
+	}
+
+	// 1. Begin a transaction.
+	// 2. (A) Start a query, (B) begin Tx rollback through a ctx cancel.
+	// 3. Check if 2.A has committed in Tx (pass) or outside of Tx (fail).
+	sendQuery := make(chan struct{})
+	hookTxGrabConn = func() {
+		cancel()
+		<-sendQuery
+	}
+	rollbackHook = func() {
+		close(sendQuery)
+	}
+	defer func() {
+		hookTxGrabConn = nil
+		rollbackHook = nil
+	}()
+
+	err = tx.QueryRow("SELECT|tx_status|tx_status|").Scan(&txStatus)
+	if err != nil {
+		// A failure here would be expected if skipDirtySession was not set to true above.
+		t.Fatal(err)
+	}
+	if g, w := txStatus, "transaction"; g != w {
+		t.Fatalf("tx_status=%q, wanted %q", g, w)
+	}
+}
+
+// Issue32530 encounters an issue where a connection may
+// expire right after it comes out of a used connection pool
+// even when a new connection is requested.
+func TestConnExpiresFreshOutOfPool(t *testing.T) {
+	execCases := []struct {
+		expired  bool
+		badReset bool
+	}{
+		{false, false},
+		{true, false},
+		{false, true},
+	}
+
+	t0 := time.Unix(1000000, 0)
+	offset := time.Duration(0)
+	offsetMu := sync.RWMutex{}
+
+	nowFunc = func() time.Time {
+		offsetMu.RLock()
+		defer offsetMu.RUnlock()
+		return t0.Add(offset)
+	}
+	defer func() { nowFunc = time.Now }()
+
+	ctx, cancel := context.WithCancel(context.Background())
+	defer cancel()
+
+	db := newTestDB(t, "magicquery")
+	defer closeDB(t, db)
+
+	db.SetMaxOpenConns(1)
+
+	for _, ec := range execCases {
+		ec := ec
+		name := fmt.Sprintf("expired=%t,badReset=%t", ec.expired, ec.badReset)
+		t.Run(name, func(t *testing.T) {
+			db.clearAllConns(t)
+
+			db.SetMaxIdleConns(1)
+			db.SetConnMaxLifetime(10 * time.Second)
+
+			conn, err := db.conn(ctx, alwaysNewConn)
+			if err != nil {
+				t.Fatal(err)
+			}
+
+			afterPutConn := make(chan struct{})
+			waitingForConn := make(chan struct{})
+
+			go func() {
+				conn, err := db.conn(ctx, alwaysNewConn)
+				if err != nil {
+					t.Fatal(err)
+				}
+				db.putConn(conn, err, false)
+				close(afterPutConn)
+			}()
+			go func() {
+				for {
+					db.mu.Lock()
+					ct := len(db.connRequests)
+					db.mu.Unlock()
+					if ct > 0 {
+						close(waitingForConn)
+						return
+					}
+					time.Sleep(10 * time.Millisecond)
+				}
+			}()
+
+			<-waitingForConn
+
+			offsetMu.Lock()
+			if ec.expired {
+				offset = 11 * time.Second
+			} else {
+				offset = time.Duration(0)
+			}
+			offsetMu.Unlock()
+
+			conn.ci.(*fakeConn).stickyBad = ec.badReset
+
+			db.putConn(conn, err, true)
+
+			<-afterPutConn
+		})
+	}
+}
+
 // TestIssue20575 ensures the Rows from query does not block
 // closing a transaction. Ensure Rows is closed while closing a trasaction.
 func TestIssue20575(t *testing.T) {
diff --git a/libgo/go/encoding/json/decode.go b/libgo/go/encoding/json/decode.go
index b60e2bb..86d8a69 100644
--- a/libgo/go/encoding/json/decode.go
+++ b/libgo/go/encoding/json/decode.go
@@ -213,9 +213,6 @@
 	savedError            error
 	useNumber             bool
 	disallowUnknownFields bool
-	// safeUnquote is the number of current string literal bytes that don't
-	// need to be unquoted. When negative, no bytes need unquoting.
-	safeUnquote int
 }
 
 // readIndex returns the position of the last byte read.
@@ -317,27 +314,13 @@
 Switch:
 	switch data[i-1] {
 	case '"': // string
-		// safeUnquote is initialized at -1, which means that all bytes
-		// checked so far can be unquoted at a later time with no work
-		// at all. When reaching the closing '"', if safeUnquote is
-		// still -1, all bytes can be unquoted with no work. Otherwise,
-		// only those bytes up until the first '\\' or non-ascii rune
-		// can be safely unquoted.
-		safeUnquote := -1
 		for ; i < len(data); i++ {
-			if c := data[i]; c == '\\' {
-				if safeUnquote < 0 { // first unsafe byte
-					safeUnquote = int(i - d.off)
-				}
+			switch data[i] {
+			case '\\':
 				i++ // escaped char
-			} else if c == '"' {
-				d.safeUnquote = safeUnquote
+			case '"':
 				i++ // tokenize the closing quote too
 				break Switch
-			} else if c >= utf8.RuneSelf {
-				if safeUnquote < 0 { // first unsafe byte
-					safeUnquote = int(i - d.off)
-				}
 			}
 		}
 	case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-': // number
@@ -691,7 +674,7 @@
 		start := d.readIndex()
 		d.rescanLiteral()
 		item := d.data[start:d.readIndex()]
-		key, ok := d.unquoteBytes(item)
+		key, ok := unquoteBytes(item)
 		if !ok {
 			panic(phasePanicMsg)
 		}
@@ -892,7 +875,7 @@
 			d.saveError(&UnmarshalTypeError{Value: val, Type: v.Type(), Offset: int64(d.readIndex())})
 			return nil
 		}
-		s, ok := d.unquoteBytes(item)
+		s, ok := unquoteBytes(item)
 		if !ok {
 			if fromQuoted {
 				return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())
@@ -943,7 +926,7 @@
 		}
 
 	case '"': // string
-		s, ok := d.unquoteBytes(item)
+		s, ok := unquoteBytes(item)
 		if !ok {
 			if fromQuoted {
 				return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())
@@ -1103,7 +1086,7 @@
 		start := d.readIndex()
 		d.rescanLiteral()
 		item := d.data[start:d.readIndex()]
-		key, ok := d.unquote(item)
+		key, ok := unquote(item)
 		if !ok {
 			panic(phasePanicMsg)
 		}
@@ -1152,7 +1135,7 @@
 		return c == 't'
 
 	case '"': // string
-		s, ok := d.unquote(item)
+		s, ok := unquote(item)
 		if !ok {
 			panic(phasePanicMsg)
 		}
@@ -1195,33 +1178,40 @@
 
 // unquote converts a quoted JSON string literal s into an actual string t.
 // The rules are different than for Go, so cannot use strconv.Unquote.
-// The first byte in s must be '"'.
-func (d *decodeState) unquote(s []byte) (t string, ok bool) {
-	s, ok = d.unquoteBytes(s)
+func unquote(s []byte) (t string, ok bool) {
+	s, ok = unquoteBytes(s)
 	t = string(s)
 	return
 }
 
-func (d *decodeState) unquoteBytes(s []byte) (t []byte, ok bool) {
-	// We already know that s[0] == '"'. However, we don't know that the
-	// closing quote exists in all cases, such as when the string is nested
-	// via the ",string" option.
-	if len(s) < 2 || s[len(s)-1] != '"' {
+func unquoteBytes(s []byte) (t []byte, ok bool) {
+	if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' {
 		return
 	}
 	s = s[1 : len(s)-1]
 
-	// If there are no unusual characters, no unquoting is needed, so return
-	// a slice of the original bytes.
-	r := d.safeUnquote
-	if r == -1 {
+	// Check for unusual characters. If there are none,
+	// then no unquoting is needed, so return a slice of the
+	// original bytes.
+	r := 0
+	for r < len(s) {
+		c := s[r]
+		if c == '\\' || c == '"' || c < ' ' {
+			break
+		}
+		if c < utf8.RuneSelf {
+			r++
+			continue
+		}
+		rr, size := utf8.DecodeRune(s[r:])
+		if rr == utf8.RuneError && size == 1 {
+			break
+		}
+		r += size
+	}
+	if r == len(s) {
 		return s, true
 	}
-	// Only perform up to one safe unquote for each re-scanned string
-	// literal. In some edge cases, the decoder unquotes a literal a second
-	// time, even after another literal has been re-scanned. Thus, only the
-	// first unquote can safely use safeUnquote.
-	d.safeUnquote = 0
 
 	b := make([]byte, len(s)+2*utf8.UTFMax)
 	w := copy(b, s[0:r])
diff --git a/libgo/go/encoding/json/decode_test.go b/libgo/go/encoding/json/decode_test.go
index a49181e..689cc34 100644
--- a/libgo/go/encoding/json/decode_test.go
+++ b/libgo/go/encoding/json/decode_test.go
@@ -2459,4 +2459,20 @@
 	if t1 != t2 {
 		t.Errorf("Marshal and Unmarshal roundtrip mismatch: want %q got %q", t1, t2)
 	}
+
+	// See golang.org/issues/39555.
+	input := map[textUnmarshalerString]string{"FOO": "", `"`: ""}
+
+	encoded, err := Marshal(input)
+	if err != nil {
+		t.Fatalf("Marshal unexpected error: %v", err)
+	}
+	var got map[textUnmarshalerString]string
+	if err := Unmarshal(encoded, &got); err != nil {
+		t.Fatalf("Unmarshal unexpected error: %v", err)
+	}
+	want := map[textUnmarshalerString]string{"foo": "", `"`: ""}
+	if !reflect.DeepEqual(want, got) {
+		t.Fatalf("Unexpected roundtrip result:\nwant: %q\ngot:  %q", want, got)
+	}
 }
diff --git a/libgo/go/golang.org/x/tools/go/analysis/passes/printf/printf.go b/libgo/go/golang.org/x/tools/go/analysis/passes/printf/printf.go
index a81dba9..e6177f2 100644
--- a/libgo/go/golang.org/x/tools/go/analysis/passes/printf/printf.go
+++ b/libgo/go/golang.org/x/tools/go/analysis/passes/printf/printf.go
@@ -801,6 +801,7 @@
 	{'g', sharpNumFlag, argFloat | argComplex},
 	{'G', sharpNumFlag, argFloat | argComplex},
 	{'o', sharpNumFlag, argInt | argPointer},
+	{'O', sharpNumFlag, argInt | argPointer},
 	{'p', "-#", argPointer},
 	{'q', " -+.0#", argRune | argInt | argString},
 	{'s', " -+.0", argString},
diff --git a/libgo/go/net/http/fs.go b/libgo/go/net/http/fs.go
index d214485..b8a68cc 100644
--- a/libgo/go/net/http/fs.go
+++ b/libgo/go/net/http/fs.go
@@ -411,6 +411,7 @@
 		}
 		if buf[0] == ',' {
 			buf = buf[1:]
+			continue
 		}
 		if buf[0] == '*' {
 			return condFalse
diff --git a/libgo/go/net/http/fs_test.go b/libgo/go/net/http/fs_test.go
index 435e34b..c082cee 100644
--- a/libgo/go/net/http/fs_test.go
+++ b/libgo/go/net/http/fs_test.go
@@ -849,6 +849,15 @@
 			wantStatus:      200,
 			wantContentType: "text/css; charset=utf-8",
 		},
+		"if_none_match_malformed": {
+			file:      "testdata/style.css",
+			serveETag: `"foo"`,
+			reqHeader: map[string]string{
+				"If-None-Match": `,`,
+			},
+			wantStatus:      200,
+			wantContentType: "text/css; charset=utf-8",
+		},
 		"range_good": {
 			file:      "testdata/style.css",
 			serveETag: `"A"`,
diff --git a/libgo/go/net/http/server.go b/libgo/go/net/http/server.go
index 77329b2..6e6514d 100644
--- a/libgo/go/net/http/server.go
+++ b/libgo/go/net/http/server.go
@@ -425,6 +425,16 @@
 	wants10KeepAlive bool               // HTTP/1.0 w/ Connection "keep-alive"
 	wantsClose       bool               // HTTP request has Connection "close"
 
+	// canWriteContinue is a boolean value accessed as an atomic int32
+	// that says whether or not a 100 Continue header can be written
+	// to the connection.
+	// writeContinueMu must be held while writing the header.
+	// These two fields together synchronize the body reader
+	// (the expectContinueReader, which wants to write 100 Continue)
+	// against the main writer.
+	canWriteContinue atomicBool
+	writeContinueMu  sync.Mutex
+
 	w  *bufio.Writer // buffers output in chunks to chunkWriter
 	cw chunkWriter
 
@@ -515,6 +525,7 @@
 
 func (b *atomicBool) isSet() bool { return atomic.LoadInt32((*int32)(b)) != 0 }
 func (b *atomicBool) setTrue()    { atomic.StoreInt32((*int32)(b), 1) }
+func (b *atomicBool) setFalse()   { atomic.StoreInt32((*int32)(b), 0) }
 
 // declareTrailer is called for each Trailer header when the
 // response header is written. It notes that a header will need to be
@@ -877,21 +888,27 @@
 	resp       *response
 	readCloser io.ReadCloser
 	closed     bool
-	sawEOF     bool
+	sawEOF     atomicBool
 }
 
 func (ecr *expectContinueReader) Read(p []byte) (n int, err error) {
 	if ecr.closed {
 		return 0, ErrBodyReadAfterClose
 	}
-	if !ecr.resp.wroteContinue && !ecr.resp.conn.hijacked() {
-		ecr.resp.wroteContinue = true
-		ecr.resp.conn.bufw.WriteString("HTTP/1.1 100 Continue\r\n\r\n")
-		ecr.resp.conn.bufw.Flush()
+	w := ecr.resp
+	if !w.wroteContinue && w.canWriteContinue.isSet() && !w.conn.hijacked() {
+		w.wroteContinue = true
+		w.writeContinueMu.Lock()
+		if w.canWriteContinue.isSet() {
+			w.conn.bufw.WriteString("HTTP/1.1 100 Continue\r\n\r\n")
+			w.conn.bufw.Flush()
+			w.canWriteContinue.setFalse()
+		}
+		w.writeContinueMu.Unlock()
 	}
 	n, err = ecr.readCloser.Read(p)
 	if err == io.EOF {
-		ecr.sawEOF = true
+		ecr.sawEOF.setTrue()
 	}
 	return
 }
@@ -1315,7 +1332,7 @@
 	// because we don't know if the next bytes on the wire will be
 	// the body-following-the-timer or the subsequent request.
 	// See Issue 11549.
-	if ecr, ok := w.req.Body.(*expectContinueReader); ok && !ecr.sawEOF {
+	if ecr, ok := w.req.Body.(*expectContinueReader); ok && !ecr.sawEOF.isSet() {
 		w.closeAfterReply = true
 	}
 
@@ -1565,6 +1582,17 @@
 		}
 		return 0, ErrHijacked
 	}
+
+	if w.canWriteContinue.isSet() {
+		// Body reader wants to write 100 Continue but hasn't yet.
+		// Tell it not to. The store must be done while holding the lock
+		// because the lock makes sure that there is not an active write
+		// this very moment.
+		w.writeContinueMu.Lock()
+		w.canWriteContinue.setFalse()
+		w.writeContinueMu.Unlock()
+	}
+
 	if !w.wroteHeader {
 		w.WriteHeader(StatusOK)
 	}
@@ -1876,6 +1904,7 @@
 			if req.ProtoAtLeast(1, 1) && req.ContentLength != 0 {
 				// Wrap the Body reader with one that replies on the connection
 				req.Body = &expectContinueReader{readCloser: req.Body, resp: w}
+				w.canWriteContinue.setTrue()
 			}
 		} else if req.Header.get("Expect") != "" {
 			w.sendExpectationFailed()
diff --git a/libgo/go/reflect/all_test.go b/libgo/go/reflect/all_test.go
index 33d02ae..e5ec052 100644
--- a/libgo/go/reflect/all_test.go
+++ b/libgo/go/reflect/all_test.go
@@ -789,6 +789,11 @@
 var loopy1, loopy2 Loopy
 var cycleMap1, cycleMap2, cycleMap3 map[string]interface{}
 
+type structWithSelfPtr struct {
+	p *structWithSelfPtr
+	s string
+}
+
 func init() {
 	loop1 = &loop2
 	loop2 = &loop1
@@ -845,6 +850,7 @@
 	{[]float64{math.NaN()}, self{}, true},
 	{map[float64]float64{math.NaN(): 1}, map[float64]float64{1: 2}, false},
 	{map[float64]float64{math.NaN(): 1}, self{}, true},
+	{&structWithSelfPtr{p: &structWithSelfPtr{s: "a"}}, &structWithSelfPtr{p: &structWithSelfPtr{s: "b"}}, false},
 
 	// Nil vs empty: not the same.
 	{[]int{}, []int(nil), false},
diff --git a/libgo/go/reflect/deepequal.go b/libgo/go/reflect/deepequal.go
index f2d4616..8a2bf8b 100644
--- a/libgo/go/reflect/deepequal.go
+++ b/libgo/go/reflect/deepequal.go
@@ -45,8 +45,20 @@
 	}
 
 	if hard(v1, v2) {
-		addr1 := v1.ptr
-		addr2 := v2.ptr
+		// For a Ptr or Map value, we need to check flagIndir,
+		// which we do by calling the pointer method.
+		// For Slice or Interface, flagIndir is always set,
+		// and using v.ptr suffices.
+		ptrval := func(v Value) unsafe.Pointer {
+			switch v.Kind() {
+			case Ptr, Map:
+				return v.pointer()
+			default:
+				return v.ptr
+			}
+		}
+		addr1 := ptrval(v1)
+		addr2 := ptrval(v2)
 		if uintptr(addr1) > uintptr(addr2) {
 			// Canonicalize order to reduce number of entries in visited.
 			// Assumes non-moving garbage collector.
diff --git a/libgo/go/reflect/type.go b/libgo/go/reflect/type.go
index 9c003a4..2ce1901 100644
--- a/libgo/go/reflect/type.go
+++ b/libgo/go/reflect/type.go
@@ -2477,6 +2477,7 @@
 	return t.kind&kindDirectIface == 0
 }
 
+// Note: this type must agree with runtime.bitvector.
 type bitVector struct {
 	n    uint32 // number of bits
 	data []byte
diff --git a/libgo/go/reflect/value.go b/libgo/go/reflect/value.go
index 147a9c4..7c6a3e8 100644
--- a/libgo/go/reflect/value.go
+++ b/libgo/go/reflect/value.go
@@ -2175,6 +2175,7 @@
 // assignTo returns a value v that can be assigned directly to typ.
 // It panics if v is not assignable to typ.
 // For a conversion to an interface type, target is a suggested scratch space to use.
+// target must be initialized memory (or nil).
 func (v Value) assignTo(context string, dst *rtype, target unsafe.Pointer) Value {
 	if v.flag&flagMethod != 0 {
 		v = makeMethodValue(context, v)
diff --git a/libgo/go/testing/benchmark.go b/libgo/go/testing/benchmark.go
index 88ba0f0..5276600 100644
--- a/libgo/go/testing/benchmark.go
+++ b/libgo/go/testing/benchmark.go
@@ -526,6 +526,7 @@
 			name:   "Main",
 			w:      os.Stdout,
 			chatty: *chatty,
+			bench:  true,
 		},
 		importPath: importPath,
 		benchFunc: func(b *B) {
@@ -559,6 +560,7 @@
 						name:   b.name,
 						w:      b.w,
 						chatty: b.chatty,
+						bench:  true,
 					},
 					benchFunc: b.benchFunc,
 					benchTime: b.benchTime,
@@ -624,6 +626,7 @@
 			creator: pc[:n],
 			w:       b.w,
 			chatty:  b.chatty,
+			bench:   true,
 		},
 		importPath: b.importPath,
 		benchFunc:  f,
diff --git a/libgo/go/testing/sub_test.go b/libgo/go/testing/sub_test.go
index 95f8220..8eb0084 100644
--- a/libgo/go/testing/sub_test.go
+++ b/libgo/go/testing/sub_test.go
@@ -438,8 +438,6 @@
 	}, {
 		// A chatty test should always log with fmt.Print, even if the
 		// parent test has completed.
-		// TODO(deklerk) Capture the log of fmt.Print and assert that the
-		// subtest message is not lost.
 		desc:   "log in finished sub test with chatty",
 		ok:     false,
 		chatty: true,
@@ -477,35 +475,37 @@
 		},
 	}}
 	for _, tc := range testCases {
-		ctx := newTestContext(tc.maxPar, newMatcher(regexp.MatchString, "", ""))
-		buf := &bytes.Buffer{}
-		root := &T{
-			common: common{
-				signal: make(chan bool),
-				name:   "Test",
-				w:      buf,
-				chatty: tc.chatty,
-			},
-			context: ctx,
-		}
-		ok := root.Run(tc.desc, tc.f)
-		ctx.release()
+		t.Run(tc.desc, func(t *T) {
+			ctx := newTestContext(tc.maxPar, newMatcher(regexp.MatchString, "", ""))
+			buf := &bytes.Buffer{}
+			root := &T{
+				common: common{
+					signal: make(chan bool),
+					name:   "Test",
+					w:      buf,
+					chatty: tc.chatty,
+				},
+				context: ctx,
+			}
+			ok := root.Run(tc.desc, tc.f)
+			ctx.release()
 
-		if ok != tc.ok {
-			t.Errorf("%s:ok: got %v; want %v", tc.desc, ok, tc.ok)
-		}
-		if ok != !root.Failed() {
-			t.Errorf("%s:root failed: got %v; want %v", tc.desc, !ok, root.Failed())
-		}
-		if ctx.running != 0 || ctx.numWaiting != 0 {
-			t.Errorf("%s:running and waiting non-zero: got %d and %d", tc.desc, ctx.running, ctx.numWaiting)
-		}
-		got := strings.TrimSpace(buf.String())
-		want := strings.TrimSpace(tc.output)
-		re := makeRegexp(want)
-		if ok, err := regexp.MatchString(re, got); !ok || err != nil {
-			t.Errorf("%s:output:\ngot:\n%s\nwant:\n%s", tc.desc, got, want)
-		}
+			if ok != tc.ok {
+				t.Errorf("%s:ok: got %v; want %v", tc.desc, ok, tc.ok)
+			}
+			if ok != !root.Failed() {
+				t.Errorf("%s:root failed: got %v; want %v", tc.desc, !ok, root.Failed())
+			}
+			if ctx.running != 0 || ctx.numWaiting != 0 {
+				t.Errorf("%s:running and waiting non-zero: got %d and %d", tc.desc, ctx.running, ctx.numWaiting)
+			}
+			got := strings.TrimSpace(buf.String())
+			want := strings.TrimSpace(tc.output)
+			re := makeRegexp(want)
+			if ok, err := regexp.MatchString(re, got); !ok || err != nil {
+				t.Errorf("%s:output:\ngot:\n%s\nwant:\n%s", tc.desc, got, want)
+			}
+		})
 	}
 }
 
@@ -655,43 +655,45 @@
 		},
 	}}
 	for _, tc := range testCases {
-		var ok bool
-		buf := &bytes.Buffer{}
-		// This is almost like the Benchmark function, except that we override
-		// the benchtime and catch the failure result of the subbenchmark.
-		root := &B{
-			common: common{
-				signal: make(chan bool),
-				name:   "root",
-				w:      buf,
-				chatty: tc.chatty,
-			},
-			benchFunc: func(b *B) { ok = b.Run("test", tc.f) }, // Use Run to catch failure.
-			benchTime: benchTimeFlag{d: 1 * time.Microsecond},
-		}
-		root.runN(1)
-		if ok != !tc.failed {
-			t.Errorf("%s:ok: got %v; want %v", tc.desc, ok, !tc.failed)
-		}
-		if !ok != root.Failed() {
-			t.Errorf("%s:root failed: got %v; want %v", tc.desc, !ok, root.Failed())
-		}
-		// All tests are run as subtests
-		if root.result.N != 1 {
-			t.Errorf("%s: N for parent benchmark was %d; want 1", tc.desc, root.result.N)
-		}
-		got := strings.TrimSpace(buf.String())
-		want := strings.TrimSpace(tc.output)
-		re := makeRegexp(want)
-		if ok, err := regexp.MatchString(re, got); !ok || err != nil {
-			t.Errorf("%s:output:\ngot:\n%s\nwant:\n%s", tc.desc, got, want)
-		}
+		t.Run(tc.desc, func(t *T) {
+			var ok bool
+			buf := &bytes.Buffer{}
+			// This is almost like the Benchmark function, except that we override
+			// the benchtime and catch the failure result of the subbenchmark.
+			root := &B{
+				common: common{
+					signal: make(chan bool),
+					name:   "root",
+					w:      buf,
+					chatty: tc.chatty,
+				},
+				benchFunc: func(b *B) { ok = b.Run("test", tc.f) }, // Use Run to catch failure.
+				benchTime: benchTimeFlag{d: 1 * time.Microsecond},
+			}
+			root.runN(1)
+			if ok != !tc.failed {
+				t.Errorf("%s:ok: got %v; want %v", tc.desc, ok, !tc.failed)
+			}
+			if !ok != root.Failed() {
+				t.Errorf("%s:root failed: got %v; want %v", tc.desc, !ok, root.Failed())
+			}
+			// All tests are run as subtests
+			if root.result.N != 1 {
+				t.Errorf("%s: N for parent benchmark was %d; want 1", tc.desc, root.result.N)
+			}
+			got := strings.TrimSpace(buf.String())
+			want := strings.TrimSpace(tc.output)
+			re := makeRegexp(want)
+			if ok, err := regexp.MatchString(re, got); !ok || err != nil {
+				t.Errorf("%s:output:\ngot:\n%s\nwant:\n%s", tc.desc, got, want)
+			}
+		})
 	}
 }
 
 func makeRegexp(s string) string {
 	s = regexp.QuoteMeta(s)
-	s = strings.ReplaceAll(s, ":NNN:", `:\d\d\d:`)
+	s = strings.ReplaceAll(s, ":NNN:", `:\d\d\d\d?:`)
 	s = strings.ReplaceAll(s, "N\\.NNs", `\d*\.\d*s`)
 	return s
 }
diff --git a/libgo/go/testing/testing.go b/libgo/go/testing/testing.go
index 758af74..9f47eb8 100644
--- a/libgo/go/testing/testing.go
+++ b/libgo/go/testing/testing.go
@@ -320,6 +320,7 @@
 	cpuListStr           *string
 	parallel             *int
 	testlog              *string
+	printer              *testPrinter
 
 	haveExamples bool // are there examples?
 
@@ -329,6 +330,48 @@
 	numFailed uint32 // number of test failures
 )
 
+type testPrinter struct {
+	chatty bool
+
+	lastNameMu sync.Mutex // guards lastName
+	lastName   string     // last printed test name in chatty mode
+}
+
+func newTestPrinter(chatty bool) *testPrinter {
+	return &testPrinter{
+		chatty: chatty,
+	}
+}
+
+func (p *testPrinter) Print(testName, out string) {
+	p.Fprint(os.Stdout, testName, out)
+}
+
+func (p *testPrinter) Fprint(w io.Writer, testName, out string) {
+	p.lastNameMu.Lock()
+	defer p.lastNameMu.Unlock()
+
+	if !p.chatty ||
+		strings.HasPrefix(out, "--- PASS") ||
+		strings.HasPrefix(out, "--- FAIL") ||
+		strings.HasPrefix(out, "=== CONT") ||
+		strings.HasPrefix(out, "=== RUN") {
+		p.lastName = testName
+		fmt.Fprint(w, out)
+		return
+	}
+
+	if p.lastName == "" {
+		p.lastName = testName
+	} else if p.lastName != testName {
+		// Always printed as-is, with 0 decoration or indentation. So, we skip
+		// printing to w.
+		fmt.Printf("=== CONT  %s\n", testName)
+		p.lastName = testName
+	}
+	fmt.Fprint(w, out)
+}
+
 // The maximum number of stack frames to go through when skipping helper functions for
 // the purpose of decorating log messages.
 const maxStackLen = 50
@@ -347,10 +390,11 @@
 	cleanup func()              // optional function to be called at the end of the test
 
 	chatty     bool   // A copy of the chatty flag.
+	bench      bool   // Whether the current test is a benchmark.
 	finished   bool   // Test function has completed.
-	hasSub     int32  // written atomically
-	raceErrors int    // number of races detected during test
-	runner     string // function name of tRunner running the test
+	hasSub     int32  // Written atomically.
+	raceErrors int    // Number of races detected during test.
+	runner     string // Function name of tRunner running the test.
 
 	parent   *common
 	level    int       // Nesting depth of test or benchmark.
@@ -480,9 +524,6 @@
 	buf := new(strings.Builder)
 	// Every line is indented at least 4 spaces.
 	buf.WriteString("    ")
-	if c.chatty {
-		fmt.Fprintf(buf, "%s: ", c.name)
-	}
 	fmt.Fprintf(buf, "%s:%d: ", file, line)
 	lines := strings.Split(s, "\n")
 	if l := len(lines); l > 1 && lines[l-1] == "" {
@@ -501,12 +542,12 @@
 
 // flushToParent writes c.output to the parent after first writing the header
 // with the given format and arguments.
-func (c *common) flushToParent(format string, args ...interface{}) {
+func (c *common) flushToParent(testName, format string, args ...interface{}) {
 	p := c.parent
 	p.mu.Lock()
 	defer p.mu.Unlock()
 
-	fmt.Fprintf(p.w, format, args...)
+	printer.Fprint(p.w, testName, fmt.Sprintf(format, args...))
 
 	c.mu.Lock()
 	defer c.mu.Unlock()
@@ -680,7 +721,14 @@
 		panic("Log in goroutine after " + c.name + " has completed")
 	} else {
 		if c.chatty {
-			fmt.Print(c.decorate(s, depth+1))
+			if c.bench {
+				// Benchmarks don't print === CONT, so we should skip the test
+				// printer and just print straight to stdout.
+				fmt.Print(c.decorate(s, depth+1))
+			} else {
+				printer.Print(c.name, c.decorate(s, depth+1))
+			}
+
 			return
 		}
 		c.output = append(c.output, c.decorate(s, depth+1)...)
@@ -909,7 +957,7 @@
 		for ; root.parent != nil; root = root.parent {
 		}
 		root.mu.Lock()
-		fmt.Fprintf(root.w, "=== CONT  %s\n", t.name)
+		printer.Fprint(root.w, t.name, fmt.Sprintf("=== CONT  %s\n", t.name))
 		root.mu.Unlock()
 	}
 
@@ -968,7 +1016,7 @@
 				root.duration += time.Since(root.start)
 				d := root.duration
 				root.mu.Unlock()
-				root.flushToParent("--- FAIL: %s (%s)\n", root.name, fmtDuration(d))
+				root.flushToParent(root.name, "--- FAIL: %s (%s)\n", root.name, fmtDuration(d))
 				if r := root.parent.runCleanup(recoverAndReturnPanic); r != nil {
 					fmt.Fprintf(root.parent.w, "cleanup panicked with %v", r)
 				}
@@ -1067,7 +1115,7 @@
 		for ; root.parent != nil; root = root.parent {
 		}
 		root.mu.Lock()
-		fmt.Fprintf(root.w, "=== RUN   %s\n", t.name)
+		printer.Fprint(root.w, t.name, fmt.Sprintf("=== RUN   %s\n", t.name))
 		root.mu.Unlock()
 	}
 	// Instead of reducing the running count of this test before calling the
@@ -1215,6 +1263,8 @@
 		flag.Parse()
 	}
 
+	printer = newTestPrinter(Verbose())
+
 	if *parallel < 1 {
 		fmt.Fprintln(os.Stderr, "testing: -parallel can only be given a positive integer")
 		flag.Usage()
@@ -1254,12 +1304,12 @@
 	dstr := fmtDuration(t.duration)
 	format := "--- %s: %s (%s)\n"
 	if t.Failed() {
-		t.flushToParent(format, "FAIL", t.name, dstr)
+		t.flushToParent(t.name, format, "FAIL", t.name, dstr)
 	} else if t.chatty {
 		if t.Skipped() {
-			t.flushToParent(format, "SKIP", t.name, dstr)
+			t.flushToParent(t.name, format, "SKIP", t.name, dstr)
 		} else {
-			t.flushToParent(format, "PASS", t.name, dstr)
+			t.flushToParent(t.name, format, "PASS", t.name, dstr)
 		}
 	}
 }