Browse Source

Out-of-bounds checking.

cl-refactor
Christian 10 years ago
parent
commit
32f0c4f8e6
  1. 24
      libsolidity/ExpressionCompiler.cpp
  2. 49
      test/SolidityEndToEndTest.cpp

24
libsolidity/ExpressionCompiler.cpp

@ -586,11 +586,29 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
"TODO: Index acces only implemented for storage arrays.");
solAssert(!arrayType.isByteArray(), "TODO: Index acces not implemented for byte arrays.");
solAssert(_indexAccess.getIndexExpression(), "Index expression expected.");
_indexAccess.getIndexExpression()->accept(*this);
// retrieve length
if (arrayType.isDynamicallySized())
m_context << eth::Instruction::DUP2 << eth::Instruction::SLOAD;
else
m_context << arrayType.getLength();
// stack: <base_ref> <index> <length>
// check out-of-bounds access
m_context << eth::Instruction::DUP2 << eth::Instruction::LT;
eth::AssemblyItem legalAccess = m_context.appendConditionalJump();
// out-of-bounds access throws exception (just STOP for now)
m_context << eth::Instruction::STOP;
m_context << legalAccess;
// stack: <base_ref> <index>
m_context << arrayType.getBaseType()->getStorageSize() << eth::Instruction::MUL;
if (arrayType.isDynamicallySized())
{
m_context << eth::Instruction::SWAP1;
CompilerUtils(m_context).computeHashStatic();
_indexAccess.getIndexExpression()->accept(*this);
m_context << arrayType.getBaseType()->getStorageSize() << eth::Instruction::MUL
<< eth::Instruction::ADD;
}
m_context << eth::Instruction::ADD;
m_currentLValue = LValue(m_context, LValue::LValueType::Storage, _indexAccess.getType());
m_currentLValue.retrieveValueIfLValueNotRequested(_indexAccess);
}

49
test/SolidityEndToEndTest.cpp

@ -2711,6 +2711,9 @@ BOOST_AUTO_TEST_CASE(dynamic_arrays_in_storage)
}
)";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("getLengths()") == encodeArgs(0, 0));
BOOST_CHECK(callContractFunction("setLengths(uint256,uint256)", 48, 49) == bytes());
BOOST_CHECK(callContractFunction("getLengths()") == encodeArgs(48, 49));
BOOST_CHECK(callContractFunction("setIDStatic(uint256)", 11) == bytes());
BOOST_CHECK(callContractFunction("getID(uint256)", 2) == encodeArgs(11));
BOOST_CHECK(callContractFunction("setID(uint256,uint256)", 7, 8) == bytes());
@ -2719,8 +2722,50 @@ BOOST_AUTO_TEST_CASE(dynamic_arrays_in_storage)
BOOST_CHECK(callContractFunction("setData(uint256,uint256,uint256)", 8, 10, 11) == bytes());
BOOST_CHECK(callContractFunction("getData(uint256)", 7) == encodeArgs(8, 9));
BOOST_CHECK(callContractFunction("getData(uint256)", 8) == encodeArgs(10, 11));
BOOST_CHECK(callContractFunction("setLengths(uint256,uint256)", 48, 49) == bytes());
BOOST_CHECK(callContractFunction("getLengths()") == encodeArgs(48, 49));
}
BOOST_AUTO_TEST_CASE(fixed_out_of_bounds_array_access)
{
char const* sourceCode = R"(
contract c {
uint[4] data;
function set(uint index, uint value) returns (bool) { data[index] = value; return true; }
function get(uint index) returns (uint) { return data[index]; }
function length() returns (uint) { return data.length; }
}
)";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("length()") == encodeArgs(4));
BOOST_CHECK(callContractFunction("set(uint256,uint256)", 3, 4) == encodeArgs(true));
BOOST_CHECK(callContractFunction("set(uint256,uint256)", 4, 5) == bytes());
BOOST_CHECK(callContractFunction("set(uint256,uint256)", 400, 5) == bytes());
BOOST_CHECK(callContractFunction("get(uint256)", 3) == encodeArgs(4));
BOOST_CHECK(callContractFunction("get(uint256)", 4) == bytes());
BOOST_CHECK(callContractFunction("get(uint256)", 400) == bytes());
BOOST_CHECK(callContractFunction("length()") == encodeArgs(4));
}
BOOST_AUTO_TEST_CASE(dynamic_out_of_bounds_array_access)
{
char const* sourceCode = R"(
contract c {
uint[] data;
function enlarge(uint amount) returns (uint) { return data.length += amount; }
function set(uint index, uint value) returns (bool) { data[index] = value; return true; }
function get(uint index) returns (uint) { return data[index]; }
function length() returns (uint) { return data.length; }
}
)";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("length()") == encodeArgs(0));
BOOST_CHECK(callContractFunction("get(uint256)", 3) == bytes());
BOOST_CHECK(callContractFunction("enlarge(uint256)", 4) == encodeArgs(4));
BOOST_CHECK(callContractFunction("length()") == encodeArgs(4));
BOOST_CHECK(callContractFunction("set(uint256,uint256)", 3, 4) == encodeArgs(true));
BOOST_CHECK(callContractFunction("get(uint256)", 3) == encodeArgs(4));
BOOST_CHECK(callContractFunction("length()") == encodeArgs(4));
BOOST_CHECK(callContractFunction("set(uint256,uint256)", 4, 8) == bytes());
BOOST_CHECK(callContractFunction("length()") == encodeArgs(4));
}
BOOST_AUTO_TEST_SUITE_END()

Loading…
Cancel
Save