From bf493a91993630bac952fe28ffddeb9ab8085785 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 28 Oct 2014 02:51:39 +0100 Subject: [PATCH] PoC-7: 6. Illegal to jump into pushdata. --- libevm/VM.cpp | 1 + libevm/VM.h | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/libevm/VM.cpp b/libevm/VM.cpp index e47237d5a..c9bf81c15 100644 --- a/libevm/VM.cpp +++ b/libevm/VM.cpp @@ -29,4 +29,5 @@ void VM::reset(u256 _gas) { m_gas = _gas; m_curPC = 0; + m_jumpDests.reset(); } diff --git a/libevm/VM.h b/libevm/VM.h index e5502b484..e81ddb475 100644 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -84,6 +84,7 @@ private: u256 m_curPC = 0; bytes m_temp; u256s m_stack; + std::set m_jumpDests; }; } @@ -93,6 +94,16 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con { auto memNeed = [](dev::u256 _offset, dev::u256 _size) { return _size ? _offset + _size : 0; }; + if (m_jumpDests.empty()) + { + m_jumpDests.insert(0); + for (unsigned i = 1; i < _ext.code.size(); ++i) + if (_ext.code[i] == (byte)Instruction::JUMPDEST) + m_jumpDests.insert(i + 1); + else if (_ext.code[i] >= (byte)Instruction::PUSH1 && _ext.code[i] <= (byte)Instruction::PUSH32) + i += _ext.code[i] - (int)Instruction::PUSH1 + 1; + } + u256 nextPC = m_curPC + 1; auto osteps = _steps; for (bool stopped = false; !stopped && _steps--; m_curPC = nextPC, nextPC = m_curPC + 1) @@ -678,7 +689,7 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con break; case Instruction::JUMP: nextPC = m_stack.back(); - if (nextPC && (Instruction)_ext.getCode(nextPC - 1) != Instruction::JUMPDEST) + if (!m_jumpDests.count((unsigned)nextPC)) BOOST_THROW_EXCEPTION(BadJumpDestination()); m_stack.pop_back(); break; @@ -686,7 +697,7 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con if (m_stack[m_stack.size() - 2]) { nextPC = m_stack.back(); - if (nextPC && (Instruction)_ext.getCode(nextPC - 1) != Instruction::JUMPDEST) + if (!m_jumpDests.count((unsigned)nextPC)) BOOST_THROW_EXCEPTION(BadJumpDestination()); } m_stack.pop_back();