diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index c78b4f59f..0ab9cbebd 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -339,7 +339,13 @@ func (v *VM) execute(ctx *Context, op Instruction) { case OVER: b := v.estack.Pop() + if b == nil { + panic("no top-level element found") + } a := v.estack.Peek(0) + if a == nil { + panic("no second element found") + } v.estack.Push(b) v.estack.Push(a) @@ -349,6 +355,9 @@ func (v *VM) execute(ctx *Context, op Instruction) { panic("negative stack item returned") } a := v.estack.Peek(n) + if a == nil { + panic("no nth element found") + } v.estack.Push(a) case ROLL: diff --git a/pkg/vm/vm_test.go b/pkg/vm/vm_test.go index 1e365e26d..635a8feea 100644 --- a/pkg/vm/vm_test.go +++ b/pkg/vm/vm_test.go @@ -339,6 +339,35 @@ func TestXTUCKgood(t *testing.T) { assert.Equal(t, int64(topelement), vm.estack.Peek(xtuckdepth).BigInt().Int64()) } +func TestOVERbadNoitem(t *testing.T) { + prog := makeProgram(OVER) + vm := load(prog) + vm.estack.PushVal(1) + vm.Run() + assert.Equal(t, true, vm.state.HasFlag(faultState)) +} + +func TestOVERbadNoitems(t *testing.T) { + prog := makeProgram(OVER) + vm := load(prog) + vm.Run() + assert.Equal(t, true, vm.state.HasFlag(faultState)) +} + +func TestOVERgood(t *testing.T) { + prog := makeProgram(OVER) + vm := load(prog) + vm.estack.PushVal(42) + vm.estack.PushVal(34) + vm.Run() + assert.Equal(t, false, vm.state.HasFlag(faultState)) + assert.Equal(t, int64(42), vm.estack.Peek(0).BigInt().Int64()) + assert.Equal(t, int64(34), vm.estack.Peek(1).BigInt().Int64()) + assert.Equal(t, int64(42), vm.estack.Peek(2).BigInt().Int64()) + assert.Equal(t, 3, vm.estack.Len()) +} + + func makeProgram(opcodes ...Instruction) []byte { prog := make([]byte, len(opcodes)+1) // RET for i := 0; i < len(opcodes); i++ {