mirror of
https://github.com/golang/go
synced 2024-11-18 10:34:51 -07:00
reflect: adjust access to unexported embedded structs
This CL changes reflect to allow access to exported fields and methods in unexported embedded structs for gccgo and after gc has been adjusted to disallow access to embedded unexported structs. Adresses #12367, #7363, #11007, and #7247. Change-Id: If80536eab35abcd25300d8ddc2d27d5c42d7e78e Reviewed-on: https://go-review.googlesource.com/14010 Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
parent
fb7178e7cc
commit
adf9b30e55
@ -8,13 +8,13 @@ import "unsafe"
|
|||||||
|
|
||||||
// MakeRO returns a copy of v with the read-only flag set.
|
// MakeRO returns a copy of v with the read-only flag set.
|
||||||
func MakeRO(v Value) Value {
|
func MakeRO(v Value) Value {
|
||||||
v.flag |= flagRO
|
v.flag |= flagStickyRO
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsRO reports whether v's read-only flag is set.
|
// IsRO reports whether v's read-only flag is set.
|
||||||
func IsRO(v Value) bool {
|
func IsRO(v Value) bool {
|
||||||
return v.flag&flagRO != 0
|
return v.flag&flagStickyRO != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
var CallGC = &callGC
|
var CallGC = &callGC
|
||||||
|
@ -496,7 +496,7 @@ func (t *uncommonType) Method(i int) (m Method) {
|
|||||||
fl := flag(Func)
|
fl := flag(Func)
|
||||||
if p.pkgPath != nil {
|
if p.pkgPath != nil {
|
||||||
m.PkgPath = *p.pkgPath
|
m.PkgPath = *p.pkgPath
|
||||||
fl |= flagRO
|
fl |= flagStickyRO
|
||||||
}
|
}
|
||||||
mt := p.typ
|
mt := p.typ
|
||||||
m.Type = mt
|
m.Type = mt
|
||||||
|
@ -44,7 +44,8 @@ type Value struct {
|
|||||||
|
|
||||||
// flag holds metadata about the value.
|
// flag holds metadata about the value.
|
||||||
// The lowest bits are flag bits:
|
// The lowest bits are flag bits:
|
||||||
// - flagRO: obtained via unexported field, so read-only
|
// - flagStickyRO: obtained via unexported not embedded field, so read-only
|
||||||
|
// - flagEmbedRO: obtained via unexported embedded field, so read-only
|
||||||
// - flagIndir: val holds a pointer to the data
|
// - flagIndir: val holds a pointer to the data
|
||||||
// - flagAddr: v.CanAddr is true (implies flagIndir)
|
// - flagAddr: v.CanAddr is true (implies flagIndir)
|
||||||
// - flagMethod: v is a method value.
|
// - flagMethod: v is a method value.
|
||||||
@ -67,11 +68,13 @@ type flag uintptr
|
|||||||
const (
|
const (
|
||||||
flagKindWidth = 5 // there are 27 kinds
|
flagKindWidth = 5 // there are 27 kinds
|
||||||
flagKindMask flag = 1<<flagKindWidth - 1
|
flagKindMask flag = 1<<flagKindWidth - 1
|
||||||
flagRO flag = 1 << 5
|
flagStickyRO flag = 1 << 5
|
||||||
flagIndir flag = 1 << 6
|
flagEmbedRO flag = 1 << 6
|
||||||
flagAddr flag = 1 << 7
|
flagIndir flag = 1 << 7
|
||||||
flagMethod flag = 1 << 8
|
flagAddr flag = 1 << 8
|
||||||
flagMethodShift = 9
|
flagMethod flag = 1 << 9
|
||||||
|
flagMethodShift = 10
|
||||||
|
flagRO flag = flagStickyRO | flagEmbedRO
|
||||||
)
|
)
|
||||||
|
|
||||||
func (f flag) kind() Kind {
|
func (f flag) kind() Kind {
|
||||||
@ -745,11 +748,15 @@ func (v Value) Field(i int) Value {
|
|||||||
field := &tt.fields[i]
|
field := &tt.fields[i]
|
||||||
typ := field.typ
|
typ := field.typ
|
||||||
|
|
||||||
// Inherit permission bits from v.
|
// Inherit permission bits from v, but clear flagEmbedRO.
|
||||||
fl := v.flag&(flagRO|flagIndir|flagAddr) | flag(typ.Kind())
|
fl := v.flag&(flagStickyRO|flagIndir|flagAddr) | flag(typ.Kind())
|
||||||
// Using an unexported field forces flagRO.
|
// Using an unexported field forces flagRO.
|
||||||
if field.pkgPath != nil {
|
if field.pkgPath != nil {
|
||||||
fl |= flagRO
|
if field.name == nil {
|
||||||
|
fl |= flagEmbedRO
|
||||||
|
} else {
|
||||||
|
fl |= flagStickyRO
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Either flagIndir is set and v.ptr points at struct,
|
// Either flagIndir is set and v.ptr points at struct,
|
||||||
// or flagIndir is not set and v.ptr is the actual struct data.
|
// or flagIndir is not set and v.ptr is the actual struct data.
|
||||||
@ -1104,7 +1111,7 @@ func (v Value) Method(i int) Value {
|
|||||||
if v.typ.Kind() == Interface && v.IsNil() {
|
if v.typ.Kind() == Interface && v.IsNil() {
|
||||||
panic("reflect: Method on nil interface value")
|
panic("reflect: Method on nil interface value")
|
||||||
}
|
}
|
||||||
fl := v.flag & (flagRO | flagIndir)
|
fl := v.flag & (flagStickyRO | flagIndir) // Clear flagEmbedRO
|
||||||
fl |= flag(Func)
|
fl |= flag(Func)
|
||||||
fl |= flag(i)<<flagMethodShift | flagMethod
|
fl |= flag(i)<<flagMethodShift | flagMethod
|
||||||
return Value{v.typ, v.ptr, fl}
|
return Value{v.typ, v.ptr, fl}
|
||||||
|
Loading…
Reference in New Issue
Block a user