Throw on division by zero.

This commit is contained in:
chriseth 2016-08-12 16:50:37 +02:00
parent e4578982c6
commit e7084d9e16
3 changed files with 33 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 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). 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 .. index:: address, balance, send, call, callcode, delegatecall
.. _address: .. _address:

View File

@ -1324,11 +1324,18 @@ void ExpressionCompiler::appendArithmeticOperatorCode(Token::Value _operator, Ty
m_context << Instruction::MUL; m_context << Instruction::MUL;
break; break;
case Token::Div: case Token::Div:
m_context << (c_isSigned ? Instruction::SDIV : Instruction::DIV);
break;
case Token::Mod: 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; break;
}
case Token::Exp: case Token::Exp:
m_context << Instruction::EXP; m_context << Instruction::EXP;
break; break;

View File

@ -6208,6 +6208,27 @@ BOOST_AUTO_TEST_CASE(addmod_mulmod)
BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(0))); 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) BOOST_AUTO_TEST_CASE(string_allocation_bug)
{ {
char const* sourceCode = R"( char const* sourceCode = R"(