mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
[ewasm] Terminate on out-of-bounds access in EwasmInterpreter
This commit is contained in:
parent
f42280f5c9
commit
bcd31daf94
@ -115,8 +115,6 @@ uint64_t popcnt(uint64_t _v)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
using u512 = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<512, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>>;
|
|
||||||
|
|
||||||
u256 EwasmBuiltinInterpreter::evalBuiltin(
|
u256 EwasmBuiltinInterpreter::evalBuiltin(
|
||||||
YulString _functionName,
|
YulString _functionName,
|
||||||
vector<Expression> const& _arguments,
|
vector<Expression> const& _arguments,
|
||||||
@ -144,7 +142,7 @@ u256 EwasmBuiltinInterpreter::evalBuiltin(
|
|||||||
else if (fun == "datacopy")
|
else if (fun == "datacopy")
|
||||||
{
|
{
|
||||||
// This is identical to codecopy.
|
// This is identical to codecopy.
|
||||||
if (accessMemory(_evaluatedArguments.at(0), _evaluatedArguments.at(2)))
|
accessMemory(_evaluatedArguments.at(0), _evaluatedArguments.at(2));
|
||||||
copyZeroExtended(
|
copyZeroExtended(
|
||||||
m_state.memory,
|
m_state.memory,
|
||||||
m_state.code,
|
m_state.code,
|
||||||
@ -324,7 +322,7 @@ u256 EwasmBuiltinInterpreter::evalEthBuiltin(string const& _fun, vector<uint64_t
|
|||||||
{
|
{
|
||||||
if (arg[1] + arg[2] < arg[1] || arg[1] + arg[2] > m_state.calldata.size())
|
if (arg[1] + arg[2] < arg[1] || arg[1] + arg[2] > m_state.calldata.size())
|
||||||
throw ExplicitlyTerminated();
|
throw ExplicitlyTerminated();
|
||||||
if (accessMemory(arg[0], arg[2]))
|
accessMemory(arg[0], arg[2]);
|
||||||
copyZeroExtended(
|
copyZeroExtended(
|
||||||
m_state.memory, m_state.calldata,
|
m_state.memory, m_state.calldata,
|
||||||
size_t(arg[0]), size_t(arg[1]), size_t(arg[2])
|
size_t(arg[0]), size_t(arg[1]), size_t(arg[2])
|
||||||
@ -377,7 +375,7 @@ u256 EwasmBuiltinInterpreter::evalEthBuiltin(string const& _fun, vector<uint64_t
|
|||||||
}
|
}
|
||||||
else if (_fun == "codeCopy")
|
else if (_fun == "codeCopy")
|
||||||
{
|
{
|
||||||
if (accessMemory(arg[0], arg[2]))
|
accessMemory(arg[0], arg[2]);
|
||||||
copyZeroExtended(
|
copyZeroExtended(
|
||||||
m_state.memory, m_state.code,
|
m_state.memory, m_state.code,
|
||||||
size_t(arg[0]), size_t(arg[1]), size_t(arg[2])
|
size_t(arg[0]), size_t(arg[1]), size_t(arg[2])
|
||||||
@ -407,7 +405,7 @@ u256 EwasmBuiltinInterpreter::evalEthBuiltin(string const& _fun, vector<uint64_t
|
|||||||
else if (_fun == "externalCodeCopy")
|
else if (_fun == "externalCodeCopy")
|
||||||
{
|
{
|
||||||
readAddress(arg[0]);
|
readAddress(arg[0]);
|
||||||
if (accessMemory(arg[1], arg[3]))
|
accessMemory(arg[1], arg[3]);
|
||||||
// TODO this way extcodecopy and codecopy do the same thing.
|
// TODO this way extcodecopy and codecopy do the same thing.
|
||||||
copyZeroExtended(
|
copyZeroExtended(
|
||||||
m_state.memory, m_state.code,
|
m_state.memory, m_state.code,
|
||||||
@ -454,7 +452,7 @@ u256 EwasmBuiltinInterpreter::evalEthBuiltin(string const& _fun, vector<uint64_t
|
|||||||
else if (_fun == "finish")
|
else if (_fun == "finish")
|
||||||
{
|
{
|
||||||
bytes data;
|
bytes data;
|
||||||
if (accessMemory(arg[0], arg[1]))
|
accessMemory(arg[0], arg[1]);
|
||||||
data = readMemory(arg[0], arg[1]);
|
data = readMemory(arg[0], arg[1]);
|
||||||
logTrace(evmasm::Instruction::RETURN, {}, data);
|
logTrace(evmasm::Instruction::RETURN, {}, data);
|
||||||
throw ExplicitlyTerminated();
|
throw ExplicitlyTerminated();
|
||||||
@ -462,7 +460,7 @@ u256 EwasmBuiltinInterpreter::evalEthBuiltin(string const& _fun, vector<uint64_t
|
|||||||
else if (_fun == "revert")
|
else if (_fun == "revert")
|
||||||
{
|
{
|
||||||
bytes data;
|
bytes data;
|
||||||
if (accessMemory(arg[0], arg[1]))
|
accessMemory(arg[0], arg[1]);
|
||||||
data = readMemory(arg[0], arg[1]);
|
data = readMemory(arg[0], arg[1]);
|
||||||
logTrace(evmasm::Instruction::REVERT, {}, data);
|
logTrace(evmasm::Instruction::REVERT, {}, data);
|
||||||
throw ExplicitlyTerminated();
|
throw ExplicitlyTerminated();
|
||||||
@ -473,7 +471,7 @@ u256 EwasmBuiltinInterpreter::evalEthBuiltin(string const& _fun, vector<uint64_t
|
|||||||
{
|
{
|
||||||
if (arg[1] + arg[2] < arg[1] || arg[1] + arg[2] > m_state.returndata.size())
|
if (arg[1] + arg[2] < arg[1] || arg[1] + arg[2] > m_state.returndata.size())
|
||||||
throw ExplicitlyTerminated();
|
throw ExplicitlyTerminated();
|
||||||
if (accessMemory(arg[0], arg[2]))
|
accessMemory(arg[0], arg[2]);
|
||||||
copyZeroExtended(
|
copyZeroExtended(
|
||||||
m_state.memory, m_state.calldata,
|
m_state.memory, m_state.calldata,
|
||||||
size_t(arg[0]), size_t(arg[1]), size_t(arg[2])
|
size_t(arg[0]), size_t(arg[1]), size_t(arg[2])
|
||||||
@ -494,18 +492,15 @@ u256 EwasmBuiltinInterpreter::evalEthBuiltin(string const& _fun, vector<uint64_t
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EwasmBuiltinInterpreter::accessMemory(u256 const& _offset, u256 const& _size)
|
void EwasmBuiltinInterpreter::accessMemory(u256 const& _offset, u256 const& _size)
|
||||||
{
|
{
|
||||||
if (((_offset + _size) >= _offset) && ((_offset + _size + 0x1f) >= (_offset + _size)))
|
// Single WebAssembly page.
|
||||||
{
|
// TODO: Support expansion in this interpreter.
|
||||||
u256 newSize = (_offset + _size + 0x1f) & ~u256(0x1f);
|
m_state.msize = 65536;
|
||||||
m_state.msize = max(m_state.msize, newSize);
|
|
||||||
return _size <= 0xffff;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
m_state.msize = u256(-1);
|
|
||||||
|
|
||||||
return false;
|
if (((_offset + _size) < _offset) || ((_offset + _size) > m_state.msize))
|
||||||
|
// Ewasm throws out of bounds exception as opposed to the EVM.
|
||||||
|
throw ExplicitlyTerminated();
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes EwasmBuiltinInterpreter::readMemory(uint64_t _offset, uint64_t _size)
|
bytes EwasmBuiltinInterpreter::readMemory(uint64_t _offset, uint64_t _size)
|
||||||
|
@ -91,8 +91,7 @@ private:
|
|||||||
|
|
||||||
/// Checks if the memory access is not too large for the interpreter and adjusts
|
/// Checks if the memory access is not too large for the interpreter and adjusts
|
||||||
/// msize accordingly.
|
/// msize accordingly.
|
||||||
/// @returns false if the amount of bytes read is lager than 0xffff
|
void accessMemory(u256 const& _offset, u256 const& _size = 32);
|
||||||
bool accessMemory(u256 const& _offset, u256 const& _size = 32);
|
|
||||||
/// @returns the memory contents at the provided address.
|
/// @returns the memory contents at the provided address.
|
||||||
/// Does not adjust msize, use @a accessMemory for that
|
/// Does not adjust msize, use @a accessMemory for that
|
||||||
bytes readMemory(uint64_t _offset, uint64_t _size = 32);
|
bytes readMemory(uint64_t _offset, uint64_t _size = 32);
|
||||||
|
Loading…
Reference in New Issue
Block a user