From a647541dec18c1766e7c2cfc17051c173396f273 Mon Sep 17 00:00:00 2001 From: smblucker Date: Mon, 7 May 2018 13:02:06 -0400 Subject: [PATCH] Implementing INVALID opcode Signed-off-by: smblucker --- execution/evm/asm/opcodes.go | 2 ++ execution/evm/vm.go | 8 ++++++-- execution/evm/vm_test.go | 20 ++++++++++++++++++++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/execution/evm/asm/opcodes.go b/execution/evm/asm/opcodes.go index 0db53834f..8dd393402 100644 --- a/execution/evm/asm/opcodes.go +++ b/execution/evm/asm/opcodes.go @@ -189,6 +189,7 @@ const ( // 0x70 range - other STATICCALL = 0xfa REVERT = 0xfd + INVALID = 0xfe SELFDESTRUCT = 0xff ) @@ -347,6 +348,7 @@ var opCodeNames = map[OpCode]string{ STATICCALL: "STATICCALL", // 0x70 range - other REVERT: "REVERT", + INVALID: "INVALID", SELFDESTRUCT: "SELFDESTRUCT", } diff --git a/execution/evm/vm.go b/execution/evm/vm.go index 5597fe037..35a3ac63a 100644 --- a/execution/evm/vm.go +++ b/execution/evm/vm.go @@ -48,6 +48,7 @@ var ( ErrDataStackUnderflow = errors.New("Data stack underflow") ErrInvalidContract = errors.New("Invalid contract") ErrNativeContractCodeCopy = errors.New("Tried to copy native contract code") + ErrExecutionAborted = errors.New("Execution aborted") ErrExecutionReverted = errors.New("Execution reverted") ) @@ -1039,6 +1040,9 @@ func (vm *VM) call(caller acm.Account, callee acm.MutableAccount, code, input [] vm.Debugf(" => [%v, %v] (%d) 0x%X\n", offset, size, len(output), output) return output, ErrExecutionReverted + case INVALID: //0xFE + return nil, ErrExecutionAborted + case SELFDESTRUCT: // 0xFF addr := stack.Pop() if useGasNegative(gas, GasGetAccount, &err) { @@ -1079,8 +1083,8 @@ func (vm *VM) call(caller acm.Account, callee acm.MutableAccount, code, input [] case STATICCALL, SHL, SHR, SAR, RETURNDATASIZE, RETURNDATACOPY: return nil, fmt.Errorf("%s not yet implemented", op.Name()) default: - vm.Debugf("(pc) %-3v Invalid opcode %X\n", pc, op) - return nil, fmt.Errorf("invalid opcode %X", op) + vm.Debugf("(pc) %-3v Unknown opcode %X\n", pc, op) + return nil, fmt.Errorf("unknown opcode %X", op) } pc++ } diff --git a/execution/evm/vm_test.go b/execution/evm/vm_test.go index 27ce07708..23f942a8c 100644 --- a/execution/evm/vm_test.go +++ b/execution/evm/vm_test.go @@ -374,6 +374,26 @@ func TestMsgSender(t *testing.T) { } +func TestInvalid(t *testing.T) { + ourVm := NewVM(newAppState(), newParams(), acm.ZeroAddress, nil, logger) + + // Create accounts + account1 := newAccount(1) + account2 := newAccount(1, 0, 1) + + var gas uint64 = 100000 + + bytecode := MustSplice(PUSH32, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, 0x20, 0x6D, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, PUSH1, 0x00, MSTORE, PUSH1, 0x0E, PUSH1, 0x00, INVALID) + + output, err := ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas) + expected := "call error: " + ErrExecutionAborted.Error() + assert.EqualError(t, err, expected) + t.Logf("Output: %v Error: %v\n", output, err) + +} + // These code segment helpers exercise the MSTORE MLOAD MSTORE cycle to test // both of the memory operations. Each MSTORE is done on the memory boundary // (at MSIZE) which Solidity uses to find guaranteed unallocated memory.