diff --git a/src/cmd/compile/internal/gc/reflect.go b/src/cmd/compile/internal/gc/reflect.go index ea771622c2..47ac541822 100644 --- a/src/cmd/compile/internal/gc/reflect.go +++ b/src/cmd/compile/internal/gc/reflect.go @@ -1285,7 +1285,14 @@ ok: // limited to the dev.boringcrypto branch and avoids // much more invasive effects elsewhere. omitFieldForAwfulBoringCryptoKludge := func(t *types.Field) bool { - return strings.HasPrefix(myimportpath, "crypto/") && t.Sym != nil && t.Sym.Name == "boring" + if t.Sym == nil || t.Sym.Name != "boring" || t.Sym.Pkg == nil { + return false + } + path := t.Sym.Pkg.Path + if t.Sym.Pkg == localpkg { + path = myimportpath + } + return strings.HasPrefix(path, "crypto/") } n := 0 diff --git a/src/internal/boringtest/boring.go b/src/internal/boringtest/boring.go new file mode 100644 index 0000000000..bea1276e69 --- /dev/null +++ b/src/internal/boringtest/boring.go @@ -0,0 +1,8 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Nothing to see here but the tests. +// This file keeps 'go install internal/...' working. + +package boring diff --git a/src/internal/boringtest/boring_test.go b/src/internal/boringtest/boring_test.go new file mode 100644 index 0000000000..a6b07eda70 --- /dev/null +++ b/src/internal/boringtest/boring_test.go @@ -0,0 +1,47 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Like crypto/rsa/boring_test.go but outside the crypto/ tree. +// Tests what happens if a package outside the crypto/ tree +// "adopts" a struct definition. This happens in golang.org/x/crypto/ssh. + +package boring + +import ( + "crypto/rand" + "crypto/rsa" + "encoding/asn1" + "reflect" + "testing" +) + +type publicKey rsa.PublicKey + +func TestBoringASN1Marshal(t *testing.T) { + k, err := rsa.GenerateKey(rand.Reader, 128) + if err != nil { + t.Fatal(err) + } + pk := (*publicKey)(&k.PublicKey) + // This used to fail, because of the unexported 'boring' field. + // Now the compiler hides it [sic]. + _, err = asn1.Marshal(*pk) + if err != nil { + t.Fatal(err) + } +} + +func TestBoringDeepEqual(t *testing.T) { + k0, err := rsa.GenerateKey(rand.Reader, 128) + if err != nil { + t.Fatal(err) + } + k := (*publicKey)(&k0.PublicKey) + k2 := *k + rsa.EncryptPKCS1v15(rand.Reader, (*rsa.PublicKey)(&k2), []byte("hello")) // initialize hidden boring field + if !reflect.DeepEqual(k, &k2) { + // compiler should be hiding the boring field from reflection + t.Fatalf("DeepEqual compared boring fields") + } +}