diff --git a/src/reflect/value.go b/src/reflect/value.go index cb784df6..e00863d0 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -168,8 +168,7 @@ func (v Value) IsValid() bool { } func (v Value) CanInterface() bool { - // No Value types of private data can be constructed at the moment. - return true + return v.isExported() } func (v Value) CanAddr() bool { @@ -502,6 +501,9 @@ func (v Value) Index(i int) Value { // Extract a character from a string. // A string is never stored directly in the interface, but always as a // pointer to the string value. + // Keeping valueFlagExported if set, but don't set valueFlagIndirect + // otherwise CanSet will return true for string elements (which is bad, + // strings are read-only). s := *(*stringHeader)(v.value) if uint(i) >= uint(s.len) { panic("reflect: string index out of range") @@ -509,6 +511,7 @@ func (v Value) Index(i int) Value { return Value{ typecode: Uint8.basicType(), value: unsafe.Pointer(uintptr(*(*uint8)(unsafe.Pointer(uintptr(s.data) + uintptr(i))))), + flags: v.flags & valueFlagExported, } case Array: // Extract an element from the array. diff --git a/testdata/reflect.go b/testdata/reflect.go index 4524cc1a..06bec575 100644 --- a/testdata/reflect.go +++ b/testdata/reflect.go @@ -415,6 +415,9 @@ func showValue(rv reflect.Value, indent string) { if rv.CanAddr() { print(" addrable=true") } + if !rv.CanInterface() { + print(" caninterface=false") + } if !rt.Comparable() { print(" comparable=false") } diff --git a/testdata/reflect.txt b/testdata/reflect.txt index f2b455aa..26d7b8b4 100644 --- a/testdata/reflect.txt +++ b/testdata/reflect.txt @@ -236,7 +236,7 @@ reflect type: struct tag: embedded: true exported: false - reflect type: interface + reflect type: interface caninterface=false interface nil: true reflect type: struct @@ -245,19 +245,19 @@ reflect type: struct tag: embedded: false exported: false - reflect type: uint8 + reflect type: uint8 caninterface=false uint: 42 field: 1 b tag: embedded: false exported: false - reflect type: int16 + reflect type: int16 caninterface=false int: 321 field: 2 c tag: embedded: false exported: false - reflect type: int8 + reflect type: int8 caninterface=false int: 123 reflect type: struct comparable=false struct: 5 @@ -265,45 +265,45 @@ reflect type: struct comparable=false tag: foo:"bar" embedded: false exported: false - reflect type: int + reflect type: int caninterface=false int: 5 field: 1 some tag: embedded: false exported: false - reflect type: struct + reflect type: struct caninterface=false struct: 2 field: 0 X tag: embedded: false exported: true - reflect type: int16 + reflect type: int16 caninterface=false int: -5 field: 1 Y tag: embedded: false exported: true - reflect type: int16 + reflect type: int16 caninterface=false int: 3 field: 2 zero tag: embedded: false exported: false - reflect type: struct + reflect type: struct caninterface=false struct: 0 field: 3 buf tag: embedded: false exported: false - reflect type: slice comparable=false + reflect type: slice caninterface=false comparable=false slice: uint8 2 2 pointer: true nil: false indexing: 0 - reflect type: uint8 addrable=true + reflect type: uint8 addrable=true caninterface=false uint: 71 indexing: 1 - reflect type: uint8 addrable=true + reflect type: uint8 addrable=true caninterface=false uint: 111 field: 4 Buf tag: @@ -325,14 +325,14 @@ reflect type: ptr tag: description:"chain" embedded: false exported: false - reflect type: ptr addrable=true + reflect type: ptr addrable=true caninterface=false pointer: false struct nil: true field: 1 foo tag: embedded: false exported: false - reflect type: int addrable=true + reflect type: int addrable=true caninterface=false int: 42 reflect type: slice comparable=false slice: interface 3 3