Skip to content

Commit d232290

Browse files
authored
Merge branch 'master' into fix/vm-jump-offset
Signed-off-by: Anton Medvedev <anton@medv.io>
2 parents ce66a2b + a2a9f37 commit d232290

File tree

2 files changed

+56
-0
lines changed

2 files changed

+56
-0
lines changed

vm/vm.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,10 +625,16 @@ func (vm *VM) push(value any) {
625625
}
626626

627627
func (vm *VM) current() any {
628+
if len(vm.Stack) == 0 {
629+
panic("stack underflow")
630+
}
628631
return vm.Stack[len(vm.Stack)-1]
629632
}
630633

631634
func (vm *VM) pop() any {
635+
if len(vm.Stack) == 0 {
636+
panic("stack underflow")
637+
}
632638
value := vm.Stack[len(vm.Stack)-1]
633639
vm.Stack = vm.Stack[:len(vm.Stack)-1]
634640
return value

vm/vm_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1429,3 +1429,53 @@ func TestVM_OpJump_NegativeOffset(t *testing.T) {
14291429
require.Error(t, err)
14301430
require.Contains(t, err.Error(), "negative jump offset is invalid")
14311431
}
1432+
1433+
func TestVM_StackUnderflow(t *testing.T) {
1434+
tests := []struct {
1435+
name string
1436+
bytecode []vm.Opcode
1437+
args []int
1438+
expectError string
1439+
}{
1440+
{
1441+
name: "pop after push",
1442+
bytecode: []vm.Opcode{vm.OpInt, vm.OpPop},
1443+
args: []int{42, 0},
1444+
},
1445+
{
1446+
name: "underflow after valid operations",
1447+
bytecode: []vm.Opcode{vm.OpInt, vm.OpInt, vm.OpPop, vm.OpPop, vm.OpPop},
1448+
args: []int{1, 2, 0, 0, 0},
1449+
expectError: "stack underflow",
1450+
},
1451+
{
1452+
name: "pop on empty stack",
1453+
bytecode: []vm.Opcode{vm.OpPop},
1454+
args: []int{0},
1455+
expectError: "stack underflow",
1456+
},
1457+
{
1458+
name: "pop after push",
1459+
bytecode: []vm.Opcode{vm.OpInt, vm.OpPop},
1460+
args: []int{123, 0},
1461+
},
1462+
}
1463+
1464+
for _, tt := range tests {
1465+
t.Run(tt.name, func(t *testing.T) {
1466+
program := &vm.Program{
1467+
Bytecode: tt.bytecode,
1468+
Arguments: tt.args,
1469+
Constants: []any{},
1470+
}
1471+
1472+
_, err := vm.Run(program, nil)
1473+
if tt.expectError != "" {
1474+
require.Error(t, err)
1475+
require.Contains(t, err.Error(), tt.expectError)
1476+
} else {
1477+
require.NoError(t, err)
1478+
}
1479+
})
1480+
}
1481+
}

0 commit comments

Comments
 (0)