Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: addressability problem #2689

Closed
wants to merge 29 commits into from
Closed
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions gnovm/pkg/gnolang/alloc.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,14 +196,16 @@ func (alloc *Allocator) NewString(s string) StringValue {
func (alloc *Allocator) NewListArray(n int) *ArrayValue {
alloc.AllocateListArray(int64(n))
return &ArrayValue{
List: make([]TypedValue, n),
List: make([]TypedValue, n),
NotAddressible: true,
}
}

func (alloc *Allocator) NewDataArray(n int) *ArrayValue {
alloc.AllocateDataArray(int64(n))
return &ArrayValue{
Data: make([]byte, n),
Data: make([]byte, n),
NotAddressible: true,
}
}

Expand Down
1 change: 1 addition & 0 deletions gnovm/pkg/gnolang/gonative.go
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,7 @@ func go2GnoValue2(alloc *Allocator, store Store, rv reflect.Value, recursive boo
}
}
tv.V = av
tv.NotAddressable = av.NotAddressible
}
case reflect.Slice:
rvl := rv.Len()
Expand Down
5 changes: 5 additions & 0 deletions gnovm/pkg/gnolang/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -2087,6 +2087,11 @@ func (m *Machine) PopAsPointer(lx Expr) PointerValue {
case *IndexExpr:
iv := m.PopValue()
xv := m.PopValue()

if xv.NotAddressable {
panic(fmt.Sprintf("PopAsPointer: expr not addressable: %+v\n", xv))
}

return xv.GetPointerAtIndex(m.Alloc, m.Store, iv)
case *SelectorExpr:
xv := m.PopValue()
Expand Down
20 changes: 18 additions & 2 deletions gnovm/pkg/gnolang/op_expressions.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ func (m *Machine) doOpIndex1() {
}
iv := m.PopValue() // index
xv := m.PeekValue(1) // x

if xv.NotAddressable {
petar-dambovaliev marked this conversation as resolved.
Show resolved Hide resolved
panic(fmt.Sprintf("doOpIndex1: expr not addressable: %+v\n", xv))
}

switch ct := baseOf(xv.T).(type) {
case *MapType:
mv := xv.V.(*MapValue)
Expand Down Expand Up @@ -44,6 +49,11 @@ func (m *Machine) doOpIndex2() {
}
iv := m.PeekValue(1) // index
xv := m.PeekValue(2) // x

if xv.NotAddressable {
petar-dambovaliev marked this conversation as resolved.
Show resolved Hide resolved
panic(fmt.Sprintf("doOpIndex2: expr not addressable: %+v\n", xv))
}

switch ct := baseOf(xv.T).(type) {
case *MapType:
vt := ct.Value
Expand Down Expand Up @@ -105,6 +115,11 @@ func (m *Machine) doOpSlice() {
}
// slice base x
xv := m.PopValue()

if xv.NotAddressable {
panic(fmt.Sprintf("doOpSlice: expr not addressable: %+v\n", xv))
}

// if a is a pointer to an array, a[low : high : max] is
// shorthand for (*a)[low : high : max]
if xv.T.Kind() == PointerKind &&
Expand Down Expand Up @@ -550,8 +565,9 @@ func (m *Machine) doOpArrayLit() {
}
// push value
m.PushValue(TypedValue{
T: at,
V: av,
T: at,
V: av,
NotAddressable: av.NotAddressible,
})
}

Expand Down
74 changes: 67 additions & 7 deletions gnovm/pkg/gnolang/values.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ import (
"github.com/gnolang/gno/tm2/pkg/crypto"
)

type Addressable interface {
Addressable()
}

// ----------------------------------------
// (runtime) Value

Expand Down Expand Up @@ -186,6 +190,17 @@ type PointerValue struct {
Key *TypedValue `json:",omitempty"` // for maps.
}

func (pv *PointerValue) Addressable() {
if pv.TV == nil {
return
}

pv.TV.NotAddressable = false
if iface, ok := pv.TV.V.(Addressable); ok {
iface.Addressable()
}
}

const (
PointerIndexBlockBlank = -1 // for the "_" identifier in blocks
PointerIndexMap = -2 // Base is Map, use Key.
Expand All @@ -211,6 +226,8 @@ func (pv *PointerValue) GetBase(store Store) Object {
// TODO: document as something that enables into-native assignment.
// TODO: maybe consider this as entrypoint for DataByteValue too?
func (pv PointerValue) Assign2(alloc *Allocator, store Store, rlm *Realm, tv2 TypedValue, cu bool) {
tv2.Addressable()
petar-dambovaliev marked this conversation as resolved.
Show resolved Hide resolved

// Special cases.
if pv.Index == PointerIndexNative {
// Special case if extended object && native.
Expand Down Expand Up @@ -315,8 +332,17 @@ func (pv PointerValue) Deref() (tv TypedValue) {

type ArrayValue struct {
ObjectInfo
List []TypedValue
Data []byte
List []TypedValue
Data []byte
NotAddressible bool
petar-dambovaliev marked this conversation as resolved.
Show resolved Hide resolved
}

func (av *ArrayValue) Addressable() {
av.NotAddressible = false

for i := range av.List {
av.List[i].Addressable()
}
}

// NOTE: Result should not be written to,
Expand Down Expand Up @@ -392,6 +418,7 @@ func (av *ArrayValue) Copy(alloc *Allocator) *ArrayValue {
if av.Data == nil {
av2 := alloc.NewListArray(len(av.List))
copy(av2.List, av.List)
av2.NotAddressible = av.NotAddressible
return av2
}
av2 := alloc.NewDataArray(len(av.Data))
Expand All @@ -409,6 +436,12 @@ type SliceValue struct {
Maxcap int
}

func (sv *SliceValue) Addressable() {
if iface, ok := sv.Base.(Addressable); ok {
iface.Addressable()
}
}

func (sv *SliceValue) GetBase(store Store) *ArrayValue {
switch cv := sv.Base.(type) {
case nil:
Expand Down Expand Up @@ -454,6 +487,12 @@ type StructValue struct {
Fields []TypedValue
}

func (sv *StructValue) Addressable() {
for i := range sv.Fields {
sv.Fields[i].Addressable()
}
}

// TODO handle unexported fields in debug, and also ensure in the preprocessor.
func (sv *StructValue) GetPointerTo(store Store, path ValuePath) PointerValue {
if debug {
Expand Down Expand Up @@ -955,9 +994,19 @@ func (nv *NativeValue) Copy(alloc *Allocator) *NativeValue {
// TypedValue (is not a value, but a tuple)

type TypedValue struct {
T Type `json:",omitempty"` // never nil
V Value `json:",omitempty"` // an untyped value
N [8]byte `json:",omitempty"` // numeric bytes
T Type `json:",omitempty"` // never nil
V Value `json:",omitempty"` // an untyped value
N [8]byte `json:",omitempty"` // numeric bytes
NotAddressable bool `json:"-"`
}

func (tv *TypedValue) Addressable() {
tv.NotAddressable = false
if p, ok := tv.V.(PointerValue); ok {
p.Addressable()
} else if iface, ok := tv.V.(Addressable); ok {
iface.Addressable()
}
}

func (tv *TypedValue) IsDefined() bool {
Expand Down Expand Up @@ -2589,9 +2638,20 @@ func defaultTypedValue(alloc *Allocator, t Type) TypedValue {
if t.Kind() == InterfaceKind {
return TypedValue{}
}

dv := defaultValue(alloc, t)

var naddr bool

switch v := dv.(type) {
case *ArrayValue:
naddr = v.NotAddressible
}

return TypedValue{
T: t,
V: defaultValue(alloc, t),
T: t,
V: dv,
NotAddressable: naddr,
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ func main() {
// }
// }
// ],
// "NotAddressible": false,
// "ObjectInfo": {
// "ID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:6",
// "ModTime": "0",
Expand Down
12 changes: 12 additions & 0 deletions gnovm/tests/files/notaddressable1.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package main

func main() {
foo()[:]
}

func foo() [2]byte {
return [2]byte{1, 2}
}

// Error:
// doOpSlice: expr not addressable: (array[0x0102] [2]uint8)
13 changes: 13 additions & 0 deletions gnovm/tests/files/notaddressable2.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package main

func main() {
arr := &getArray()[0]
println(arr)
}

func getArray() [3]int {
return [3]int{1, 2, 3}
}

// Error:
// PopAsPointer: expr not addressable: (array[(1 int),(2 int),(3 int)] [3]int)
1 change: 1 addition & 0 deletions gnovm/tests/files/zrealm_tests0_stdlibs.gno
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ func main() {
// }
// }
// ],
// "NotAddressible": false,
// "ObjectInfo": {
// "ID": "0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:16",
// "ModTime": "0",
Expand Down
Loading