Merge pull request #888 from chriseth/throwOnDivZero

Throw on division by zero.
This commit is contained in:
chriseth 2016-08-17 16:43:13 +02:00 committed by GitHub
commit d6579a0a5f
4 changed files with 41 additions and 3 deletions

View File

@ -57,6 +57,8 @@ Operators:
Division always truncates (it just maps to the DIV opcode of the EVM), but it does not truncate if both
operators are :ref:`literals<rational_literals>` (or literal expressions).
Division by zero and modulus with zero throws an exception.
.. index:: address, balance, send, call, callcode, delegatecall
.. _address:

View File

@ -1324,11 +1324,18 @@ void ExpressionCompiler::appendArithmeticOperatorCode(Token::Value _operator, Ty
m_context << Instruction::MUL;
break;
case Token::Div:
m_context << (c_isSigned ? Instruction::SDIV : Instruction::DIV);
break;
case Token::Mod:
m_context << (c_isSigned ? Instruction::SMOD : Instruction::MOD);
{
// Test for division by zero
m_context << Instruction::DUP2 << Instruction::ISZERO;
m_context.appendConditionalJumpTo(m_context.errorTag());
if (_operator == Token::Div)
m_context << (c_isSigned ? Instruction::SDIV : Instruction::DIV);
else
m_context << (c_isSigned ? Instruction::SMOD : Instruction::MOD);
break;
}
case Token::Exp:
m_context << Instruction::EXP;
break;

View File

@ -6209,6 +6209,27 @@ BOOST_AUTO_TEST_CASE(addmod_mulmod)
BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(0)));
}
BOOST_AUTO_TEST_CASE(divisiod_by_zero)
{
char const* sourceCode = R"(
contract C {
function div(uint a, uint b) returns (uint) {
return a / b;
}
function mod(uint a, uint b) returns (uint) {
return a % b;
}
}
)";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("div(uint256,uint256)", 7, 2) == encodeArgs(u256(3)));
// throws
BOOST_CHECK(callContractFunction("div(uint256,uint256)", 7, 0) == encodeArgs());
BOOST_CHECK(callContractFunction("mod(uint256,uint256)", 7, 2) == encodeArgs(u256(1)));
// throws
BOOST_CHECK(callContractFunction("mod(uint256,uint256)", 7, 0) == encodeArgs());
}
BOOST_AUTO_TEST_CASE(string_allocation_bug)
{
char const* sourceCode = R"(

View File

@ -323,7 +323,15 @@ BOOST_AUTO_TEST_CASE(arithmetics)
byte(Instruction::OR),
byte(Instruction::SUB),
byte(Instruction::ADD),
byte(Instruction::DUP2),
byte(Instruction::ISZERO),
byte(Instruction::PUSH1), 0x2,
byte(Instruction::JUMPI),
byte(Instruction::MOD),
byte(Instruction::DUP2),
byte(Instruction::ISZERO),
byte(Instruction::PUSH1), 0x2,
byte(Instruction::JUMPI),
byte(Instruction::DIV),
byte(Instruction::MUL)});
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());