vm: make cloning limits a bit more effective

Take actual reference counter value into account.
This commit is contained in:
Roman Khimov 2021-07-11 19:37:06 +03:00
parent cfe41abd35
commit 4000dd692c
2 changed files with 7 additions and 5 deletions

View file

@ -1056,7 +1056,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
itemElem := v.estack.Pop() itemElem := v.estack.Pop()
arrElem := v.estack.Pop() arrElem := v.estack.Pop()
val, err := cloneIfStruct(itemElem.value) val, err := cloneIfStruct(itemElem.value, MaxStackSize-v.refs.size)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -1373,7 +1373,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
src := t.Value().([]stackitem.Item) src := t.Value().([]stackitem.Item)
arr = make([]stackitem.Item, len(src)) arr = make([]stackitem.Item, len(src))
for i := range src { for i := range src {
arr[i], err = cloneIfStruct(src[i]) arr[i], err = cloneIfStruct(src[i], MaxStackSize-v.refs.size)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -1381,7 +1381,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
case *stackitem.Map: case *stackitem.Map:
arr = make([]stackitem.Item, 0, t.Len()) arr = make([]stackitem.Item, 0, t.Len())
for k := range t.Value().([]stackitem.MapElement) { for k := range t.Value().([]stackitem.MapElement) {
elem, err := cloneIfStruct(t.Value().([]stackitem.MapElement)[k].Value) elem, err := cloneIfStruct(t.Value().([]stackitem.MapElement)[k].Value, MaxStackSize-v.refs.size)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -1751,10 +1751,10 @@ func checkMultisig1(v *VM, curve elliptic.Curve, h []byte, pkeys [][]byte, sig [
return false return false
} }
func cloneIfStruct(item stackitem.Item) (stackitem.Item, error) { func cloneIfStruct(item stackitem.Item, limit int) (stackitem.Item, error) {
switch it := item.(type) { switch it := item.(type) {
case *stackitem.Struct: case *stackitem.Struct:
return it.Clone(MaxStackSize) return it.Clone(limit)
default: default:
return it, nil return it, nil
} }

View file

@ -2440,6 +2440,8 @@ func TestNestedStructClone(t *testing.T) {
"5601c2c501fe0360589d604a12c0db415824f7cf45", "5601c2c501fe0360589d604a12c0db415824f7cf45",
// VALUES for map with deeply nested struct. // VALUES for map with deeply nested struct.
"5601c84a11c501fe0060589d604a12c0db415824f7d0cd45", "5601c84a11c501fe0060589d604a12c0db415824f7d0cd45",
// VALUES for a lot of not-so-deep nested structs.
"5601c5000a60589d604a12c0db415824f701fe03504a519d4a102afa01ff03c0cd45",
} }
for _, h := range progs { for _, h := range progs {
prog, err := hex.DecodeString(h) prog, err := hex.DecodeString(h)