aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/reflect/all_test.go11
-rw-r--r--src/reflect/value.go11
2 files changed, 19 insertions, 3 deletions
diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go
index 69d5378049..6cc1c9abad 100644
--- a/src/reflect/all_test.go
+++ b/src/reflect/all_test.go
@@ -8001,6 +8001,17 @@ func TestSetIter(t *testing.T) {
if got := *y.Interface().(*int); got != b {
t.Errorf("pointer incorrect: got %d want %d", got, b)
}
+
+ // Make sure we panic assigning from an unexported field.
+ m = ValueOf(struct{ m map[string]int }{data}).Field(0)
+ for iter := m.MapRange(); iter.Next(); {
+ shouldPanic("using value obtained using unexported field", func() {
+ k.SetIterKey(iter)
+ })
+ shouldPanic("using value obtained using unexported field", func() {
+ v.SetIterValue(iter)
+ })
+ }
}
func TestMethodCallValueCodePtr(t *testing.T) {
diff --git a/src/reflect/value.go b/src/reflect/value.go
index 2589a6dd18..5276af6fd6 100644
--- a/src/reflect/value.go
+++ b/src/reflect/value.go
@@ -1837,7 +1837,8 @@ func (iter *MapIter) Key() Value {
// SetIterKey assigns to v the key of iter's current map entry.
// It is equivalent to v.Set(iter.Key()), but it avoids allocating a new Value.
-// As in Go, the key must be assignable to v's type.
+// As in Go, the key must be assignable to v's type and
+// must not be derived from an unexported field.
func (v Value) SetIterKey(iter *MapIter) {
if !iter.hiter.initialized() {
panic("reflect: Value.SetIterKey called before Next")
@@ -1856,6 +1857,7 @@ func (v Value) SetIterKey(iter *MapIter) {
t := (*mapType)(unsafe.Pointer(iter.m.typ))
ktype := t.key
+ iter.m.mustBeExported() // do not let unexported m leak
key := Value{ktype, iterkey, iter.m.flag | flag(ktype.Kind()) | flagIndir}
key = key.assignTo("reflect.MapIter.SetKey", v.typ, target)
typedmemmove(v.typ, v.ptr, key.ptr)
@@ -1878,7 +1880,8 @@ func (iter *MapIter) Value() Value {
// SetIterValue assigns to v the value of iter's current map entry.
// It is equivalent to v.Set(iter.Value()), but it avoids allocating a new Value.
-// As in Go, the value must be assignable to v's type.
+// As in Go, the value must be assignable to v's type and
+// must not be derived from an unexported field.
func (v Value) SetIterValue(iter *MapIter) {
if !iter.hiter.initialized() {
panic("reflect: Value.SetIterValue called before Next")
@@ -1897,6 +1900,7 @@ func (v Value) SetIterValue(iter *MapIter) {
t := (*mapType)(unsafe.Pointer(iter.m.typ))
vtype := t.elem
+ iter.m.mustBeExported() // do not let unexported m leak
elem := Value{vtype, iterelem, iter.m.flag | flag(vtype.Kind()) | flagIndir}
elem = elem.assignTo("reflect.MapIter.SetValue", v.typ, target)
typedmemmove(v.typ, v.ptr, elem.ptr)
@@ -2218,7 +2222,8 @@ func (v Value) send(x Value, nb bool) (selected bool) {
// Set assigns x to the value v.
// It panics if CanSet returns false.
-// As in Go, x's value must be assignable to v's type.
+// As in Go, x's value must be assignable to v's type and
+// must not be derived from an unexported field.
func (v Value) Set(x Value) {
v.mustBeAssignable()
x.mustBeExported() // do not let unexported x leak