mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Merge pull request #888 from chriseth/throwOnDivZero
Throw on division by zero.
This commit is contained in:
		
						commit
						d6579a0a5f
					
				| @ -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: | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -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"( | ||||
|  | ||||
| @ -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()); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user