]> Cypherpunks repositories - gostls13.git/commitdiff
reflect: make Value.Interface return immutable data
authorRuss Cox <rsc@golang.org>
Thu, 1 Mar 2012 16:48:27 +0000 (11:48 -0500)
committerRuss Cox <rsc@golang.org>
Thu, 1 Mar 2012 16:48:27 +0000 (11:48 -0500)
Fixes #3134.

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/5713049

src/pkg/reflect/all_test.go
src/pkg/reflect/value.go

index b21a99ec5c2c63eb6644edaac0455b60852686a2..6bb061398148f9f89841a1b8721ee081d6ca0b9f 100644 (file)
@@ -1743,3 +1743,15 @@ func isValid(v Value) {
                panic("zero Value")
        }
 }
+
+func TestAlias(t *testing.T) {
+       x := string("hello")
+       v := ValueOf(&x).Elem()
+       oldvalue := v.Interface()
+       v.SetString("world")
+       newvalue := v.Interface()
+
+       if oldvalue != "hello" || newvalue != "world" {
+               t.Errorf("aliasing: old=%q new=%q, want hello, world", oldvalue, newvalue)
+       }
+}
index df65dcfa5b601827849c3ad79ac6fc9cb5247fc3..39f8acdea4626a91a088257792aee6dbc5d6e267 100644 (file)
@@ -842,6 +842,16 @@ func valueInterface(v Value, safe bool) interface{} {
        var eface emptyInterface
        eface.typ = v.typ.runtimeType()
        eface.word = v.iword()
+
+       if v.flag&flagIndir != 0 && v.typ.size > ptrSize {
+               // eface.word is a pointer to the actual data,
+               // which might be changed.  We need to return
+               // a pointer to unchanging data, so make a copy.
+               ptr := unsafe_New(v.typ)
+               memmove(ptr, unsafe.Pointer(eface.word), v.typ.size)
+               eface.word = iword(ptr)
+       }
+
        return *(*interface{})(unsafe.Pointer(&eface))
 }