From 32b30d76b0c855361ecdeae8ea67156518c79a66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Sun, 3 Nov 2019 19:01:53 +0100 Subject: [PATCH] interpreter: Simplify reporting stack violation --- libaleth-interpreter/VM.cpp | 246 ++++++++++++++----------------- libaleth-interpreter/VM.h | 1 - libaleth-interpreter/VMCalls.cpp | 11 -- 3 files changed, 110 insertions(+), 148 deletions(-) diff --git a/libaleth-interpreter/VM.cpp b/libaleth-interpreter/VM.cpp index e1e45785208..6aa697a2f99 100644 --- a/libaleth-interpreter/VM.cpp +++ b/libaleth-interpreter/VM.cpp @@ -1,8 +1,8 @@ // Aleth: Ethereum C++ client, tools and libraries. // Copyright 2014-2019 Aleth Authors. // Licensed under the GNU General Public License, Version 3. -#include "interpreter.h" #include "VM.h" +#include "interpreter.h" #include @@ -97,7 +97,7 @@ uint64_t VM::memNeed(intx::uint256 const& _offset, intx::uint256 const& _size) uint64_t VM::decodeJumpDest(const byte* const _code, uint64_t& _pc) { // turn 2 MSB-first bytes in the code into a native-order integer - uint64_t dest = _code[_pc++]; + uint64_t dest = _code[_pc++]; dest = (dest << 8) | _code[_pc++]; return dest; } @@ -110,13 +110,14 @@ uint64_t VM::decodeJumpvDest(const byte* const _code, uint64_t& _pc, byte _voff) // byte table[n_jumps][2] // uint64_t pc = _pc; - byte n = _code[++pc]; // byte after opcode is number of jumps - if (_voff >= n) _voff = n - 1; // if offset overflows use default jump - pc += _voff * 2; // adjust inout pc before index destination in table + byte n = _code[++pc]; // byte after opcode is number of jumps + if (_voff >= n) + _voff = n - 1; // if offset overflows use default jump + pc += _voff * 2; // adjust inout pc before index destination in table uint64_t dest = decodeJumpDest(_code, pc); - _pc += 1 + n * 2; // adust inout _pc to opcode after table + _pc += 1 + n * 2; // adust inout _pc to opcode after table return dest; } @@ -130,10 +131,10 @@ void VM::adjustStack(int _required, int _change) // adjust stack and check bounds if (m_stackEnd < m_SP + _required) - throwBadStack(_required); + throw EVMC_STACK_UNDERFLOW; m_SPP -= _change; if (m_SPP < m_stack) - throwBadStack(_required); + throw EVMC_STACK_OVERFLOW; } uint64_t VM::gasForMem(intx::uint512 const& _size) @@ -170,7 +171,7 @@ void VM::updateMem(uint64_t _newMem) void VM::logGasMem() { - unsigned n = (unsigned) m_OP - (unsigned) Instruction::LOG0; + unsigned n = (unsigned)m_OP - (unsigned)Instruction::LOG0; constexpr int64_t logDataGas = VMSchedule::logDataGas; m_runGas = toInt63( VMSchedule::logGas + VMSchedule::logTopicGas * n + logDataGas * intx::uint512(m_SP[1])); @@ -351,7 +352,7 @@ void VM::interpretCases() } NEXT - CASE(MSTORE) + CASE(MSTORE) { ON_OP(); updateMem(toInt63(m_SP[0]) + 32); @@ -361,7 +362,7 @@ void VM::interpretCases() } NEXT - CASE(MSTORE8) + CASE(MSTORE8) { ON_OP(); updateMem(toInt63(m_SP[0]) + 1); @@ -371,7 +372,7 @@ void VM::interpretCases() } NEXT - CASE(SHA3) + CASE(SHA3) { ON_OP(); constexpr int64_t sha3Gas = VMSchedule::sha3Gas; @@ -388,7 +389,7 @@ void VM::interpretCases() } NEXT - CASE(LOG0) + CASE(LOG0) { ON_OP(); if (m_message->flags & EVMC_STATIC) @@ -405,7 +406,7 @@ void VM::interpretCases() } NEXT - CASE(LOG1) + CASE(LOG1) { ON_OP(); if (m_message->flags & EVMC_STATIC) @@ -425,7 +426,7 @@ void VM::interpretCases() } NEXT - CASE(LOG2) + CASE(LOG2) { ON_OP(); if (m_message->flags & EVMC_STATIC) @@ -438,9 +439,7 @@ void VM::interpretCases() size_t dataSize = size_t(m_SP[1]); evmc_uint256be topics[] = { - intx::be::store(m_SP[2]), - intx::be::store(m_SP[3]) - }; + intx::be::store(m_SP[2]), intx::be::store(m_SP[3])}; size_t numTopics = sizeof(topics) / sizeof(topics[0]); m_context->host->emit_log( @@ -448,7 +447,7 @@ void VM::interpretCases() } NEXT - CASE(LOG3) + CASE(LOG3) { ON_OP(); if (m_message->flags & EVMC_STATIC) @@ -460,11 +459,8 @@ void VM::interpretCases() uint8_t const* data = m_mem.data() + size_t(m_SP[0]); size_t dataSize = size_t(m_SP[1]); - evmc_uint256be topics[] = { - intx::be::store(m_SP[2]), - intx::be::store(m_SP[3]), - intx::be::store(m_SP[4]) - }; + evmc_uint256be topics[] = {intx::be::store(m_SP[2]), + intx::be::store(m_SP[3]), intx::be::store(m_SP[4])}; size_t numTopics = sizeof(topics) / sizeof(topics[0]); m_context->host->emit_log( @@ -472,7 +468,7 @@ void VM::interpretCases() } NEXT - CASE(LOG4) + CASE(LOG4) { ON_OP(); if (m_message->flags & EVMC_STATIC) @@ -484,12 +480,9 @@ void VM::interpretCases() uint8_t const* data = m_mem.data() + size_t(m_SP[0]); size_t dataSize = size_t(m_SP[1]); - evmc_uint256be topics[] = { - intx::be::store(m_SP[2]), - intx::be::store(m_SP[3]), - intx::be::store(m_SP[4]), - intx::be::store(m_SP[5]) - }; + evmc_uint256be topics[] = {intx::be::store(m_SP[2]), + intx::be::store(m_SP[3]), intx::be::store(m_SP[4]), + intx::be::store(m_SP[5])}; size_t numTopics = sizeof(topics) / sizeof(topics[0]); m_context->host->emit_log( @@ -497,11 +490,12 @@ void VM::interpretCases() } NEXT - CASE(EXP) + CASE(EXP) { intx::uint256 expon = m_SP[1]; const int64_t byteCost = m_rev >= EVMC_SPURIOUS_DRAGON ? 50 : 10; - m_runGas = toInt63(VMSchedule::stepGas5 + byteCost * intx::count_significant_words(expon)); + m_runGas = toInt63( + VMSchedule::stepGas5 + byteCost * intx::count_significant_words(expon)); ON_OP(); updateIOGas(); @@ -510,31 +504,31 @@ void VM::interpretCases() } NEXT - // - // ordinary instructions - // + // + // ordinary instructions + // - CASE(ADD) + CASE(ADD) { ON_OP(); updateIOGas(); - //pops two items and pushes their sum mod 2^256. + // pops two items and pushes their sum mod 2^256. m_SPP[0] = m_SP[0] + m_SP[1]; } NEXT - CASE(MUL) + CASE(MUL) { ON_OP(); updateIOGas(); - //pops two items and pushes their product mod 2^256. + // pops two items and pushes their product mod 2^256. m_SPP[0] = m_SP[0] * m_SP[1]; } NEXT - CASE(SUB) + CASE(SUB) { ON_OP(); updateIOGas(); @@ -543,7 +537,7 @@ void VM::interpretCases() } NEXT - CASE(DIV) + CASE(DIV) { ON_OP(); updateIOGas(); @@ -552,7 +546,7 @@ void VM::interpretCases() } NEXT - CASE(SDIV) + CASE(SDIV) { ON_OP(); updateIOGas(); @@ -562,7 +556,7 @@ void VM::interpretCases() } NEXT - CASE(MOD) + CASE(MOD) { ON_OP(); updateIOGas(); @@ -571,7 +565,7 @@ void VM::interpretCases() } NEXT - CASE(SMOD) + CASE(SMOD) { ON_OP(); updateIOGas(); @@ -580,7 +574,7 @@ void VM::interpretCases() } NEXT - CASE(NOT) + CASE(NOT) { ON_OP(); updateIOGas(); @@ -589,7 +583,7 @@ void VM::interpretCases() } NEXT - CASE(LT) + CASE(LT) { ON_OP(); updateIOGas(); @@ -598,7 +592,7 @@ void VM::interpretCases() } NEXT - CASE(GT) + CASE(GT) { ON_OP(); updateIOGas(); @@ -607,7 +601,7 @@ void VM::interpretCases() } NEXT - CASE(SLT) + CASE(SLT) { ON_OP(); updateIOGas(); @@ -618,7 +612,7 @@ void VM::interpretCases() } NEXT - CASE(SGT) + CASE(SGT) { ON_OP(); updateIOGas(); @@ -629,7 +623,7 @@ void VM::interpretCases() } NEXT - CASE(EQ) + CASE(EQ) { ON_OP(); updateIOGas(); @@ -638,7 +632,7 @@ void VM::interpretCases() } NEXT - CASE(ISZERO) + CASE(ISZERO) { ON_OP(); updateIOGas(); @@ -647,7 +641,7 @@ void VM::interpretCases() } NEXT - CASE(AND) + CASE(AND) { ON_OP(); updateIOGas(); @@ -656,7 +650,7 @@ void VM::interpretCases() } NEXT - CASE(OR) + CASE(OR) { ON_OP(); updateIOGas(); @@ -665,7 +659,7 @@ void VM::interpretCases() } NEXT - CASE(XOR) + CASE(XOR) { ON_OP(); updateIOGas(); @@ -674,7 +668,7 @@ void VM::interpretCases() } NEXT - CASE(BYTE) + CASE(BYTE) { ON_OP(); updateIOGas(); @@ -683,7 +677,7 @@ void VM::interpretCases() } NEXT - CASE(SHL) + CASE(SHL) { // Pre-constantinople if (m_rev < EVMC_CONSTANTINOPLE) @@ -699,7 +693,7 @@ void VM::interpretCases() } NEXT - CASE(SHR) + CASE(SHR) { // Pre-constantinople if (m_rev < EVMC_CONSTANTINOPLE) @@ -715,7 +709,7 @@ void VM::interpretCases() } NEXT - CASE(SAR) + CASE(SAR) { // Pre-constantinople if (m_rev < EVMC_CONSTANTINOPLE) @@ -746,7 +740,7 @@ void VM::interpretCases() } NEXT - CASE(ADDMOD) + CASE(ADDMOD) { ON_OP(); updateIOGas(); @@ -755,7 +749,7 @@ void VM::interpretCases() } NEXT - CASE(MULMOD) + CASE(MULMOD) { ON_OP(); updateIOGas(); @@ -764,7 +758,7 @@ void VM::interpretCases() } NEXT - CASE(SIGNEXTEND) + CASE(SIGNEXTEND) { ON_OP(); updateIOGas(); @@ -784,16 +778,8 @@ void VM::interpretCases() } NEXT - CASE(JUMPTO) - CASE(JUMPIF) - CASE(JUMPV) - CASE(JUMPSUB) - CASE(JUMPSUBV) - CASE(RETURNSUB) - CASE(BEGINSUB) - CASE(BEGINDATA) - CASE(GETLOCAL) - CASE(PUTLOCAL) + CASE(JUMPTO) CASE(JUMPIF) CASE(JUMPV) CASE(JUMPSUB) CASE(JUMPSUBV) CASE(RETURNSUB) + CASE(BEGINSUB) CASE(BEGINDATA) CASE(GETLOCAL) CASE(PUTLOCAL) { throwBadInstruction(); } @@ -831,10 +817,7 @@ void VM::interpretCases() CASE(XPUT) CASE(XGET) CASE(XSWIZZLE) - CASE(XSHUFFLE) - { - throwBadInstruction(); - } + CASE(XSHUFFLE) { throwBadInstruction(); } CONTINUE CASE(ADDRESS) @@ -846,7 +829,7 @@ void VM::interpretCases() } NEXT - CASE(ORIGIN) + CASE(ORIGIN) { ON_OP(); updateIOGas(); @@ -855,18 +838,19 @@ void VM::interpretCases() } NEXT - CASE(BALANCE) + CASE(BALANCE) { ON_OP(); updateIOGas(); auto const address = intx::be::trunc(m_SP[0]); - m_SPP[0] = intx::be::load(m_context->host->get_balance(m_context, &address)); + m_SPP[0] = + intx::be::load(m_context->host->get_balance(m_context, &address)); } NEXT - CASE(CALLER) + CASE(CALLER) { ON_OP(); updateIOGas(); @@ -875,7 +859,7 @@ void VM::interpretCases() } NEXT - CASE(CALLVALUE) + CASE(CALLVALUE) { ON_OP(); updateIOGas(); @@ -885,7 +869,7 @@ void VM::interpretCases() NEXT - CASE(CALLDATALOAD) + CASE(CALLDATALOAD) { ON_OP(); updateIOGas(); @@ -900,7 +884,8 @@ void VM::interpretCases() else { uint8_t r[32]; - for (uint64_t i = (uint64_t)m_SP[0], e = (uint64_t)m_SP[0] + (uint64_t)32, j = 0; i < e; ++i, ++j) + for (uint64_t i = (uint64_t)m_SP[0], e = (uint64_t)m_SP[0] + (uint64_t)32, j = 0; + i < e; ++i, ++j) r[j] = i < dataSize ? data[i] : 0; m_SP[0] = intx::be::load(r); }; @@ -908,7 +893,7 @@ void VM::interpretCases() NEXT - CASE(CALLDATASIZE) + CASE(CALLDATASIZE) { ON_OP(); updateIOGas(); @@ -917,7 +902,7 @@ void VM::interpretCases() } NEXT - CASE(RETURNDATASIZE) + CASE(RETURNDATASIZE) { if (m_rev < EVMC_BYZANTIUM) throwBadInstruction(); @@ -929,7 +914,7 @@ void VM::interpretCases() } NEXT - CASE(CODESIZE) + CASE(CODESIZE) { ON_OP(); updateIOGas(); @@ -938,7 +923,7 @@ void VM::interpretCases() } NEXT - CASE(EXTCODESIZE) + CASE(EXTCODESIZE) { ON_OP(); updateIOGas(); @@ -949,7 +934,7 @@ void VM::interpretCases() } NEXT - CASE(CALLDATACOPY) + CASE(CALLDATACOPY) { ON_OP(); m_copyMemSize = toInt63(m_SP[2]); @@ -961,7 +946,7 @@ void VM::interpretCases() } NEXT - CASE(RETURNDATACOPY) + CASE(RETURNDATACOPY) { ON_OP(); if (m_rev < EVMC_BYZANTIUM) @@ -978,7 +963,7 @@ void VM::interpretCases() } NEXT - CASE(EXTCODEHASH) + CASE(EXTCODEHASH) { ON_OP(); if (m_rev < EVMC_CONSTANTINOPLE) @@ -987,11 +972,12 @@ void VM::interpretCases() updateIOGas(); auto const address = intx::be::trunc(m_SP[0]); - m_SPP[0] = intx::be::load(m_context->host->get_code_hash(m_context, &address)); + m_SPP[0] = + intx::be::load(m_context->host->get_code_hash(m_context, &address)); } NEXT - CASE(CODECOPY) + CASE(CODECOPY) { ON_OP(); m_copyMemSize = toInt63(m_SP[2]); @@ -1002,7 +988,7 @@ void VM::interpretCases() } NEXT - CASE(EXTCODECOPY) + CASE(EXTCODECOPY) { ON_OP(); uint64_t copyMemSize = toInt63(m_SP[3]); @@ -1026,7 +1012,7 @@ void VM::interpretCases() NEXT - CASE(GASPRICE) + CASE(GASPRICE) { ON_OP(); updateIOGas(); @@ -1035,7 +1021,7 @@ void VM::interpretCases() } NEXT - CASE(BLOCKHASH) + CASE(BLOCKHASH) { ON_OP(); m_runGas = VMSchedule::stepGas6; @@ -1046,14 +1032,15 @@ void VM::interpretCases() if (number < blockNumber && number >= std::max(int64_t(256), blockNumber) - 256) { - m_SPP[0] = intx::be::load(m_context->host->get_block_hash(m_context, int64_t(number))); + m_SPP[0] = intx::be::load( + m_context->host->get_block_hash(m_context, int64_t(number))); } else m_SPP[0] = 0; } NEXT - CASE(COINBASE) + CASE(COINBASE) { ON_OP(); updateIOGas(); @@ -1062,7 +1049,7 @@ void VM::interpretCases() } NEXT - CASE(TIMESTAMP) + CASE(TIMESTAMP) { ON_OP(); updateIOGas(); @@ -1071,7 +1058,7 @@ void VM::interpretCases() } NEXT - CASE(NUMBER) + CASE(NUMBER) { ON_OP(); updateIOGas(); @@ -1080,7 +1067,7 @@ void VM::interpretCases() } NEXT - CASE(DIFFICULTY) + CASE(DIFFICULTY) { ON_OP(); updateIOGas(); @@ -1089,7 +1076,7 @@ void VM::interpretCases() } NEXT - CASE(GASLIMIT) + CASE(GASLIMIT) { ON_OP(); updateIOGas(); @@ -1099,7 +1086,7 @@ void VM::interpretCases() NEXT - CASE(CHAINID) + CASE(CHAINID) { ON_OP(); @@ -1112,7 +1099,7 @@ void VM::interpretCases() } NEXT - CASE(SELFBALANCE) + CASE(SELFBALANCE) { ON_OP(); @@ -1121,11 +1108,12 @@ void VM::interpretCases() updateIOGas(); - m_SPP[0] = intx::be::load(m_context->host->get_balance(m_context, &m_message->destination)); + m_SPP[0] = intx::be::load( + m_context->host->get_balance(m_context, &m_message->destination)); } NEXT - CASE(POP) + CASE(POP) { ON_OP(); updateIOGas(); @@ -1134,7 +1122,7 @@ void VM::interpretCases() } NEXT - CASE(PUSHC) + CASE(PUSHC) { #if EVM_USE_CONSTANT_POOL ON_OP(); @@ -1283,27 +1271,14 @@ void VM::interpretCases() // the stack slot being copied into may no longer hold a uint256 // so we construct a new one in the memory, rather than assign - new(m_SPP) intx::uint256(m_SP[n]); + new (m_SPP) intx::uint256(m_SP[n]); } NEXT - CASE(SWAP1) - CASE(SWAP2) - CASE(SWAP3) - CASE(SWAP4) - CASE(SWAP5) - CASE(SWAP6) - CASE(SWAP7) - CASE(SWAP8) - CASE(SWAP9) - CASE(SWAP10) - CASE(SWAP11) - CASE(SWAP12) - CASE(SWAP13) - CASE(SWAP14) - CASE(SWAP15) - CASE(SWAP16) + CASE(SWAP1) CASE(SWAP2) CASE(SWAP3) CASE(SWAP4) CASE(SWAP5) CASE(SWAP6) CASE(SWAP7) + CASE(SWAP8) CASE(SWAP9) CASE(SWAP10) CASE(SWAP11) CASE(SWAP12) CASE(SWAP13) + CASE(SWAP14) CASE(SWAP15) CASE(SWAP16) { ON_OP(); updateIOGas(); @@ -1314,18 +1289,18 @@ void VM::interpretCases() NEXT - CASE(SLOAD) + CASE(SLOAD) { ON_OP(); updateIOGas(); auto const key = intx::be::store(m_SP[0]); - m_SPP[0] = - intx::be::load(m_context->host->get_storage(m_context, &m_message->destination, &key)); + m_SPP[0] = intx::be::load( + m_context->host->get_storage(m_context, &m_message->destination, &key)); } NEXT - CASE(SSTORE) + CASE(SSTORE) { ON_OP(); if (m_message->flags & EVMC_STATIC) @@ -1339,7 +1314,7 @@ void VM::interpretCases() auto const status = m_context->host->set_storage(m_context, &m_message->destination, &key, &value); - switch(status) + switch (status) { case EVMC_STORAGE_ADDED: m_runGas = VMSchedule::sstoreSetGas; @@ -1360,7 +1335,7 @@ void VM::interpretCases() } NEXT - CASE(PC) + CASE(PC) { ON_OP(); updateIOGas(); @@ -1369,7 +1344,7 @@ void VM::interpretCases() } NEXT - CASE(MSIZE) + CASE(MSIZE) { ON_OP(); updateIOGas(); @@ -1378,7 +1353,7 @@ void VM::interpretCases() } NEXT - CASE(GAS) + CASE(GAS) { ON_OP(); updateIOGas(); @@ -1387,7 +1362,7 @@ void VM::interpretCases() } NEXT - CASE(JUMPDEST) + CASE(JUMPDEST) { m_runGas = VMSchedule::jumpdestGas; ON_OP(); @@ -1395,8 +1370,7 @@ void VM::interpretCases() } NEXT - CASE(INVALID) - DEFAULT + CASE(INVALID) DEFAULT { if (m_OP == Instruction::INVALID) throwInvalidInstruction(); @@ -1406,5 +1380,5 @@ void VM::interpretCases() } WHILE_CASES } -} -} +} // namespace eth +} // namespace dev diff --git a/libaleth-interpreter/VM.h b/libaleth-interpreter/VM.h index 9b3658d876b..332d8e74e0f 100644 --- a/libaleth-interpreter/VM.h +++ b/libaleth-interpreter/VM.h @@ -122,7 +122,6 @@ class VM static void throwInvalidInstruction(); static void throwBadInstruction(); static void throwBadJumpDestination(); - void throwBadStack(int _removed); void throwRevertInstruction(uint64_t _offset, uint64_t _size); static void throwDisallowedStateChange(); static void throwBufferOverrun(); diff --git a/libaleth-interpreter/VMCalls.cpp b/libaleth-interpreter/VMCalls.cpp index 1108192d467..77f895f4caa 100644 --- a/libaleth-interpreter/VMCalls.cpp +++ b/libaleth-interpreter/VMCalls.cpp @@ -50,17 +50,6 @@ void VM::throwDisallowedStateChange() throw EVMC_STATIC_MODE_VIOLATION; } -// throwBadStack is called from fetchInstruction() -> adjustStack() -// its the only exception that can happen before ON_OP() log is done for an opcode case in VM.cpp -// so the call to m_onFail is needed here -void VM::throwBadStack(int _required) -{ - if (m_stackEnd - m_SPP < _required) - throw EVMC_STACK_UNDERFLOW; - else - throw EVMC_STACK_OVERFLOW; -} - void VM::throwRevertInstruction(uint64_t _offset, uint64_t _size) { m_output = owning_bytes_ref{std::move(m_mem), _offset, _size};