mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
reflect: disallow Interface method on Value obtained via unexported name
Had been allowing it for use by fmt, but it is too hard to lock down. Fix other packages not to depend on it. R=r, r CC=golang-dev https://golang.org/cl/5266054
This commit is contained in:
parent
e5f3dc8bc5
commit
304cf4dc9b
6 changed files with 288 additions and 167 deletions
|
|
@ -853,13 +853,13 @@ func TestIsNil(t *testing.T) {
|
|||
|
||||
func TestInterfaceExtraction(t *testing.T) {
|
||||
var s struct {
|
||||
w io.Writer
|
||||
W io.Writer
|
||||
}
|
||||
|
||||
s.w = os.Stdout
|
||||
s.W = os.Stdout
|
||||
v := Indirect(ValueOf(&s)).Field(0).Interface()
|
||||
if v != s.w.(interface{}) {
|
||||
t.Error("Interface() on interface: ", v, s.w)
|
||||
if v != s.W.(interface{}) {
|
||||
t.Error("Interface() on interface: ", v, s.W)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1190,18 +1190,18 @@ type D2 struct {
|
|||
}
|
||||
|
||||
type S0 struct {
|
||||
a, b, c int
|
||||
A, B, C int
|
||||
D1
|
||||
D2
|
||||
}
|
||||
|
||||
type S1 struct {
|
||||
b int
|
||||
B int
|
||||
S0
|
||||
}
|
||||
|
||||
type S2 struct {
|
||||
a int
|
||||
A int
|
||||
*S1
|
||||
}
|
||||
|
||||
|
|
@ -1216,36 +1216,36 @@ type S1y struct {
|
|||
type S3 struct {
|
||||
S1x
|
||||
S2
|
||||
d, e int
|
||||
D, E int
|
||||
*S1y
|
||||
}
|
||||
|
||||
type S4 struct {
|
||||
*S4
|
||||
a int
|
||||
A int
|
||||
}
|
||||
|
||||
var fieldTests = []FTest{
|
||||
{struct{}{}, "", nil, 0},
|
||||
{struct{}{}, "foo", nil, 0},
|
||||
{S0{a: 'a'}, "a", []int{0}, 'a'},
|
||||
{S0{}, "d", nil, 0},
|
||||
{S1{S0: S0{a: 'a'}}, "a", []int{1, 0}, 'a'},
|
||||
{S1{b: 'b'}, "b", []int{0}, 'b'},
|
||||
{struct{}{}, "Foo", nil, 0},
|
||||
{S0{A: 'a'}, "A", []int{0}, 'a'},
|
||||
{S0{}, "D", nil, 0},
|
||||
{S1{S0: S0{A: 'a'}}, "A", []int{1, 0}, 'a'},
|
||||
{S1{B: 'b'}, "B", []int{0}, 'b'},
|
||||
{S1{}, "S0", []int{1}, 0},
|
||||
{S1{S0: S0{c: 'c'}}, "c", []int{1, 2}, 'c'},
|
||||
{S2{a: 'a'}, "a", []int{0}, 'a'},
|
||||
{S1{S0: S0{C: 'c'}}, "C", []int{1, 2}, 'c'},
|
||||
{S2{A: 'a'}, "A", []int{0}, 'a'},
|
||||
{S2{}, "S1", []int{1}, 0},
|
||||
{S2{S1: &S1{b: 'b'}}, "b", []int{1, 0}, 'b'},
|
||||
{S2{S1: &S1{S0: S0{c: 'c'}}}, "c", []int{1, 1, 2}, 'c'},
|
||||
{S2{}, "d", nil, 0},
|
||||
{S2{S1: &S1{B: 'b'}}, "B", []int{1, 0}, 'b'},
|
||||
{S2{S1: &S1{S0: S0{C: 'c'}}}, "C", []int{1, 1, 2}, 'c'},
|
||||
{S2{}, "D", nil, 0},
|
||||
{S3{}, "S1", nil, 0},
|
||||
{S3{S2: S2{a: 'a'}}, "a", []int{1, 0}, 'a'},
|
||||
{S3{}, "b", nil, 0},
|
||||
{S3{d: 'd'}, "d", []int{2}, 0},
|
||||
{S3{e: 'e'}, "e", []int{3}, 'e'},
|
||||
{S4{a: 'a'}, "a", []int{1}, 'a'},
|
||||
{S4{}, "b", nil, 0},
|
||||
{S3{S2: S2{A: 'a'}}, "A", []int{1, 0}, 'a'},
|
||||
{S3{}, "B", nil, 0},
|
||||
{S3{D: 'd'}, "D", []int{2}, 0},
|
||||
{S3{E: 'e'}, "E", []int{3}, 'e'},
|
||||
{S4{A: 'a'}, "A", []int{1}, 'a'},
|
||||
{S4{}, "B", nil, 0},
|
||||
}
|
||||
|
||||
func TestFieldByIndex(t *testing.T) {
|
||||
|
|
@ -1587,3 +1587,68 @@ func TestSetBytes(t *testing.T) {
|
|||
t.Errorf("ValueOf(%p).Bytes() = %p", &x[0], &y[0])
|
||||
}
|
||||
}
|
||||
|
||||
type Private struct {
|
||||
x int
|
||||
y **int
|
||||
}
|
||||
|
||||
func (p *Private) m() {
|
||||
}
|
||||
|
||||
type Public struct {
|
||||
X int
|
||||
Y **int
|
||||
}
|
||||
|
||||
func (p *Public) M() {
|
||||
}
|
||||
|
||||
func TestUnexported(t *testing.T) {
|
||||
var pub Public
|
||||
v := ValueOf(&pub)
|
||||
isValid(v.Elem().Field(0))
|
||||
isValid(v.Elem().Field(1))
|
||||
isValid(v.Elem().FieldByName("X"))
|
||||
isValid(v.Elem().FieldByName("Y"))
|
||||
isValid(v.Type().Method(0).Func)
|
||||
isNonNil(v.Elem().Field(0).Interface())
|
||||
isNonNil(v.Elem().Field(1).Interface())
|
||||
isNonNil(v.Elem().FieldByName("X").Interface())
|
||||
isNonNil(v.Elem().FieldByName("Y").Interface())
|
||||
isNonNil(v.Type().Method(0).Func.Interface())
|
||||
|
||||
var priv Private
|
||||
v = ValueOf(&priv)
|
||||
isValid(v.Elem().Field(0))
|
||||
isValid(v.Elem().Field(1))
|
||||
isValid(v.Elem().FieldByName("x"))
|
||||
isValid(v.Elem().FieldByName("y"))
|
||||
isValid(v.Type().Method(0).Func)
|
||||
shouldPanic(func() { v.Elem().Field(0).Interface() })
|
||||
shouldPanic(func() { v.Elem().Field(1).Interface() })
|
||||
shouldPanic(func() { v.Elem().FieldByName("x").Interface() })
|
||||
shouldPanic(func() { v.Elem().FieldByName("y").Interface() })
|
||||
shouldPanic(func() { v.Type().Method(0).Func.Interface() })
|
||||
}
|
||||
|
||||
func shouldPanic(f func()) {
|
||||
defer func() {
|
||||
if recover() == nil {
|
||||
panic("did not panic")
|
||||
}
|
||||
}()
|
||||
f()
|
||||
}
|
||||
|
||||
func isNonNil(x interface{}) {
|
||||
if x == nil {
|
||||
panic("nil interface")
|
||||
}
|
||||
}
|
||||
|
||||
func isValid(v Value) {
|
||||
if !v.IsValid() {
|
||||
panic("zero Value")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue