Skip to content

Commit 0a5b33a

Browse files
rscthanm
authored andcommitted
[release-branch.go1.22] encoding/gob: make x509.Certificate marshalable again
The OID type is not exported data like most of the other x509 structs. Using it in x509.Certificate made Certificate not gob-compatible anymore, which breaks real-world code. As a temporary fix, make gob ignore that field, making it work as well as it did in Go 1.21. For Go 1.23, we anticipate adding a proper fix and removing the gob workaround. See #65633 and #66249 for more details. For #66249. For #65633. Fixes #66273. Change-Id: Idd1431d15063b3009e15d0565cd3120b9fa13f61 Reviewed-on: https://go-review.googlesource.com/c/go/+/571095 LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Rob Pike <[email protected]> Reviewed-by: Roland Shoemaker <[email protected]> Reviewed-on: https://go-review.googlesource.com/c/go/+/571715 Reviewed-by: David Chase <[email protected]>
1 parent 0c53f93 commit 0a5b33a

File tree

4 files changed

+26
-3
lines changed

4 files changed

+26
-3
lines changed

src/crypto/x509/x509.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,7 @@ type Certificate struct {
780780
PolicyIdentifiers []asn1.ObjectIdentifier
781781

782782
// Policies contains all policy identifiers included in the certificate.
783+
// In Go 1.22, encoding/gob cannot handle and ignores this field.
783784
Policies []OID
784785
}
785786

src/crypto/x509/x509_test.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"crypto/x509/pkix"
2020
"encoding/asn1"
2121
"encoding/base64"
22+
"encoding/gob"
2223
"encoding/hex"
2324
"encoding/pem"
2425
"fmt"
@@ -3999,3 +4000,13 @@ func TestCertificatePoliciesGODEBUG(t *testing.T) {
39994000
t.Errorf("cert.Policies = %v, want: %v", cert.Policies, expectPolicies)
40004001
}
40014002
}
4003+
4004+
func TestGob(t *testing.T) {
4005+
// Test that gob does not reject Certificate.
4006+
// See go.dev/issue/65633.
4007+
cert := new(Certificate)
4008+
err := gob.NewEncoder(io.Discard).Encode(cert)
4009+
if err != nil {
4010+
t.Fatal(err)
4011+
}
4012+
}

src/encoding/gob/encode.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -601,7 +601,7 @@ func compileEnc(ut *userTypeInfo, building map[*typeInfo]bool) *encEngine {
601601
if ut.externalEnc == 0 && srt.Kind() == reflect.Struct {
602602
for fieldNum, wireFieldNum := 0, 0; fieldNum < srt.NumField(); fieldNum++ {
603603
f := srt.Field(fieldNum)
604-
if !isSent(&f) {
604+
if !isSent(srt, &f) {
605605
continue
606606
}
607607
op, indir := encOpFor(f.Type, seen, building)

src/encoding/gob/type.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,7 @@ func newTypeObject(name string, ut *userTypeInfo, rt reflect.Type) (gobType, err
538538
idToTypeSlice[st.id()] = st
539539
for i := 0; i < t.NumField(); i++ {
540540
f := t.Field(i)
541-
if !isSent(&f) {
541+
if !isSent(t, &f) {
542542
continue
543543
}
544544
typ := userType(f.Type).base
@@ -576,7 +576,7 @@ func isExported(name string) bool {
576576
// isSent reports whether this struct field is to be transmitted.
577577
// It will be transmitted only if it is exported and not a chan or func field
578578
// or pointer to chan or func.
579-
func isSent(field *reflect.StructField) bool {
579+
func isSent(struct_ reflect.Type, field *reflect.StructField) bool {
580580
if !isExported(field.Name) {
581581
return false
582582
}
@@ -589,6 +589,17 @@ func isSent(field *reflect.StructField) bool {
589589
if typ.Kind() == reflect.Chan || typ.Kind() == reflect.Func {
590590
return false
591591
}
592+
593+
// Special case for Go 1.22: the x509.Certificate.Policies
594+
// field is unencodable but also unused by default.
595+
// Ignore it, so that x509.Certificate continues to be encodeable.
596+
// Go 1.23 will add the right methods so that gob can
597+
// handle the Policies field, and then we can remove this check.
598+
// See go.dev/issue/65633.
599+
if field.Name == "Policies" && struct_.PkgPath() == "crypto/x509" && struct_.Name() == "Certificate" {
600+
return false
601+
}
602+
592603
return true
593604
}
594605

0 commit comments

Comments
 (0)