mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-07 04:23:41 +00:00
reflect: check for access in the Interface method call
This fixes a type system loophole. The following program would
incorrectly run in TinyGo, while it would trigger a panic in Go:
package main
import "reflect"
func main() {
v := reflect.ValueOf(struct {
x int
}{})
x := v.Field(0).Interface()
println("x:", x.(int))
}
Playground link: https://play.golang.org/p/nvvA18XFqFC
The panic in Go is the following:
panic: reflect.Value.Interface: cannot return value obtained from unexported field or method
I've shortened it in TinyGo to save a little bit of space.
This commit is contained in:
committed by
Ron Evans
parent
46a7993fb8
commit
f800f7507c
@@ -28,6 +28,13 @@ func (v Value) isIndirect() bool {
|
||||
return v.flags&valueFlagIndirect != 0
|
||||
}
|
||||
|
||||
// isExported returns whether the value represented by this Value could be
|
||||
// accessed without violating type system constraints. For example, it is not
|
||||
// set for unexported struct fields.
|
||||
func (v Value) isExported() bool {
|
||||
return v.flags&valueFlagExported != 0
|
||||
}
|
||||
|
||||
func Indirect(v Value) Value {
|
||||
if v.Kind() != Ptr {
|
||||
return v
|
||||
@@ -51,6 +58,15 @@ func ValueOf(i interface{}) Value {
|
||||
}
|
||||
|
||||
func (v Value) Interface() interface{} {
|
||||
if !v.isExported() {
|
||||
panic("(reflect.Value).Interface: unexported")
|
||||
}
|
||||
return valueInterfaceUnsafe(v)
|
||||
}
|
||||
|
||||
// valueInterfaceUnsafe is used by the runtime to hash map keys. It should not
|
||||
// be subject to the isExported check.
|
||||
func valueInterfaceUnsafe(v Value) interface{} {
|
||||
if v.isIndirect() && v.typecode.Size() <= unsafe.Sizeof(uintptr(0)) {
|
||||
// Value was indirect but must be put back directly in the interface
|
||||
// value.
|
||||
|
||||
Reference in New Issue
Block a user