Merge pull request #438 from nspcc-dev/fix/437

vm: copy slice in NEWARRAY/NEWSTRUCT

Fixes #437.
This commit is contained in:
Roman Khimov 2019-10-22 14:36:32 +03:00 committed by GitHub
commit 558a25cbd2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 72 additions and 2 deletions

View file

@ -756,7 +756,9 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) {
item := v.estack.Pop() item := v.estack.Pop()
switch t := item.value.(type) { switch t := item.value.(type) {
case *StructItem: case *StructItem:
v.estack.PushVal(&ArrayItem{t.value}) arr := make([]StackItem, len(t.value))
copy(arr, t.value)
v.estack.PushVal(&ArrayItem{arr})
case *ArrayItem: case *ArrayItem:
v.estack.PushVal(t) v.estack.PushVal(t)
default: default:
@ -772,7 +774,9 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) {
item := v.estack.Pop() item := v.estack.Pop()
switch t := item.value.(type) { switch t := item.value.(type) {
case *ArrayItem: case *ArrayItem:
v.estack.PushVal(&StructItem{t.value}) arr := make([]StackItem, len(t.value))
copy(arr, t.value)
v.estack.PushVal(&StructItem{arr})
case *StructItem: case *StructItem:
v.estack.PushVal(t) v.estack.PushVal(t)
default: default:

View file

@ -528,6 +528,39 @@ func TestNEWARRAYStruct(t *testing.T) {
assert.Equal(t, &ArrayItem{arr}, vm.estack.Pop().value) assert.Equal(t, &ArrayItem{arr}, vm.estack.Pop().value)
} }
func testNEWARRAYIssue437(t *testing.T, i1, i2 Instruction, appended bool) {
prog := makeProgram(
PUSH2, i1,
DUP, PUSH3, APPEND,
TOALTSTACK, DUPFROMALTSTACK, i2,
DUP, PUSH4, APPEND,
FROMALTSTACK, PUSH5, APPEND)
vm := load(prog)
vm.Run()
arr := makeArrayOfFalses(4)
arr[2] = makeStackItem(3)
arr[3] = makeStackItem(4)
if appended {
arr = append(arr, makeStackItem(5))
}
assert.Equal(t, false, vm.HasFailed())
assert.Equal(t, 1, vm.estack.Len())
if i2 == NEWARRAY {
assert.Equal(t, &ArrayItem{arr}, vm.estack.Pop().value)
} else {
assert.Equal(t, &StructItem{arr}, vm.estack.Pop().value)
}
}
func TestNEWARRAYIssue437(t *testing.T) {
t.Run("Array+Array", func(t *testing.T) { testNEWARRAYIssue437(t, NEWARRAY, NEWARRAY, true) })
t.Run("Struct+Struct", func(t *testing.T) { testNEWARRAYIssue437(t, NEWSTRUCT, NEWSTRUCT, true) })
t.Run("Array+Struct", func(t *testing.T) { testNEWARRAYIssue437(t, NEWARRAY, NEWSTRUCT, false) })
t.Run("Struct+Array", func(t *testing.T) { testNEWARRAYIssue437(t, NEWSTRUCT, NEWARRAY, false) })
}
func TestNEWARRAYArray(t *testing.T) { func TestNEWARRAYArray(t *testing.T) {
prog := makeProgram(NEWARRAY) prog := makeProgram(NEWARRAY)
vm := load(prog) vm := load(prog)
@ -1732,6 +1765,39 @@ func TestREVERSEBadNotArray(t *testing.T) {
assert.Equal(t, true, vm.HasFailed()) assert.Equal(t, true, vm.HasFailed())
} }
func testREVERSEIssue437(t *testing.T, i1, i2 Instruction, reversed bool) {
prog := makeProgram(
PUSH0, i1,
DUP, PUSH1, APPEND,
DUP, PUSH2, APPEND,
DUP, i2, REVERSE)
vm := load(prog)
vm.Run()
arr := make([]StackItem, 2)
if reversed {
arr[0] = makeStackItem(2)
arr[1] = makeStackItem(1)
} else {
arr[0] = makeStackItem(1)
arr[1] = makeStackItem(2)
}
assert.Equal(t, false, vm.HasFailed())
assert.Equal(t, 1, vm.estack.Len())
if i1 == NEWARRAY {
assert.Equal(t, &ArrayItem{arr}, vm.estack.Pop().value)
} else {
assert.Equal(t, &StructItem{arr}, vm.estack.Pop().value)
}
}
func TestREVERSEIssue437(t *testing.T) {
t.Run("Array+Array", func(t *testing.T) { testREVERSEIssue437(t, NEWARRAY, NEWARRAY, true) })
t.Run("Struct+Struct", func(t *testing.T) { testREVERSEIssue437(t, NEWSTRUCT, NEWSTRUCT, true) })
t.Run("Array+Struct", func(t *testing.T) { testREVERSEIssue437(t, NEWARRAY, NEWSTRUCT, false) })
t.Run("Struct+Array", func(t *testing.T) { testREVERSEIssue437(t, NEWSTRUCT, NEWARRAY, false) })
}
func TestREVERSEGoodOneElem(t *testing.T) { func TestREVERSEGoodOneElem(t *testing.T) {
prog := makeProgram(DUP, REVERSE) prog := makeProgram(DUP, REVERSE)
elements := []int{22} elements := []int{22}