diff options
-rw-r--r-- | Changelog.md | 1 | ||||
-rw-r--r-- | libsolidity/analysis/StaticAnalyzer.cpp | 42 | ||||
-rw-r--r-- | libsolidity/analysis/StaticAnalyzer.h | 2 | ||||
-rw-r--r-- | libsolidity/ast/Types.h | 3 | ||||
-rw-r--r-- | test/libsolidity/SolidityEndToEndTest.cpp | 12 | ||||
-rw-r--r-- | test/libsolidity/SolidityNameAndTypeResolution.cpp | 14 | ||||
-rw-r--r-- | test/libsolidity/syntaxTests/constants/addmod_mulmod_rational.sol | 7 | ||||
-rw-r--r-- | test/libsolidity/syntaxTests/constants/addmod_zero.sol | 11 | ||||
-rw-r--r-- | test/libsolidity/syntaxTests/constants/division_by_zero.sol | 9 | ||||
-rw-r--r-- | test/libsolidity/syntaxTests/constants/mod_div_rational.sol | 6 | ||||
-rw-r--r-- | test/libsolidity/syntaxTests/constants/mod_zero.sol | 9 | ||||
-rw-r--r-- | test/libsolidity/syntaxTests/constants/mulmod_zero.sol | 11 | ||||
-rw-r--r-- | test/libsolidity/syntaxTests/signed_rational_modulus.sol | 8 |
13 files changed, 115 insertions, 20 deletions
diff --git a/Changelog.md b/Changelog.md index 1612fe3b..58ca2705 100644 --- a/Changelog.md +++ b/Changelog.md @@ -35,6 +35,7 @@ Bugfixes: * Type System: Make external library functions accessible. * Type System: Prevent encoding of weird types. * Static Analyzer: Fix non-deterministic order of unused variable warnings. + * Static Analyzer: Invalid arithmetic with constant expressions causes errors. ### 0.4.21 (2018-03-07) diff --git a/libsolidity/analysis/StaticAnalyzer.cpp b/libsolidity/analysis/StaticAnalyzer.cpp index 33b0e296..51aa0b28 100644 --- a/libsolidity/analysis/StaticAnalyzer.cpp +++ b/libsolidity/analysis/StaticAnalyzer.cpp @@ -21,6 +21,7 @@ */ #include <libsolidity/analysis/StaticAnalyzer.h> +#include <libsolidity/analysis/ConstantEvaluator.h> #include <libsolidity/ast/AST.h> #include <libsolidity/interface/ErrorReporter.h> #include <memory> @@ -231,6 +232,47 @@ bool StaticAnalyzer::visit(InlineAssembly const& _inlineAssembly) return true; } +bool StaticAnalyzer::visit(BinaryOperation const& _operation) +{ + if ( + _operation.rightExpression().annotation().isPure && + (_operation.getOperator() == Token::Div || _operation.getOperator() == Token::Mod) + ) + if (auto rhs = dynamic_pointer_cast<RationalNumberType const>( + ConstantEvaluator(m_errorReporter).evaluate(_operation.rightExpression()) + )) + if (rhs->isZero()) + m_errorReporter.typeError( + _operation.location(), + (_operation.getOperator() == Token::Div) ? "Division by zero." : "Modulo zero." + ); + + return true; +} + +bool StaticAnalyzer::visit(FunctionCall const& _functionCall) +{ + if (_functionCall.annotation().kind == FunctionCallKind::FunctionCall) + { + auto functionType = dynamic_pointer_cast<FunctionType const>(_functionCall.expression().annotation().type); + solAssert(functionType, ""); + if (functionType->kind() == FunctionType::Kind::AddMod || functionType->kind() == FunctionType::Kind::MulMod) + { + solAssert(_functionCall.arguments().size() == 3, ""); + if (_functionCall.arguments()[2]->annotation().isPure) + if (auto lastArg = dynamic_pointer_cast<RationalNumberType const>( + ConstantEvaluator(m_errorReporter).evaluate(*(_functionCall.arguments())[2]) + )) + if (lastArg->isZero()) + m_errorReporter.typeError( + _functionCall.location(), + "Arithmetic modulo zero." + ); + } + } + return true; +} + bigint StaticAnalyzer::structureSizeEstimate(Type const& _type, set<StructDefinition const*>& _structsSeen) { switch (_type.category()) diff --git a/libsolidity/analysis/StaticAnalyzer.h b/libsolidity/analysis/StaticAnalyzer.h index 0a806bbd..2a62e391 100644 --- a/libsolidity/analysis/StaticAnalyzer.h +++ b/libsolidity/analysis/StaticAnalyzer.h @@ -64,6 +64,8 @@ private: virtual bool visit(Return const& _return) override; virtual bool visit(MemberAccess const& _memberAccess) override; virtual bool visit(InlineAssembly const& _inlineAssembly) override; + virtual bool visit(BinaryOperation const& _operation) override; + virtual bool visit(FunctionCall const& _functionCall) override; /// @returns the size of this type in storage, including all sub-types. static bigint structureSizeEstimate(Type const& _type, std::set<StructDefinition const*>& _structsSeen); diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 05f506f1..ecfc2333 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -446,6 +446,9 @@ public: /// @returns true if the value is negative. bool isNegative() const { return m_value < 0; } + /// @returns true if the value is zero. + bool isZero() const { return m_value == 0; } + private: rational m_value; diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 39f4b03e..f7f1062d 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -7847,12 +7847,12 @@ BOOST_AUTO_TEST_CASE(addmod_mulmod_zero) { char const* sourceCode = R"( contract C { - function f() pure returns (uint) { - addmod(1, 2, 0); + function f(uint d) pure returns (uint) { + addmod(1, 2, d); return 2; } - function g() pure returns (uint) { - mulmod(1, 2, 0); + function g(uint d) pure returns (uint) { + mulmod(1, 2, d); return 2; } function h() pure returns (uint) { @@ -7865,8 +7865,8 @@ BOOST_AUTO_TEST_CASE(addmod_mulmod_zero) } )"; compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("f()"), encodeArgs()); - ABI_CHECK(callContractFunction("g()"), encodeArgs()); + ABI_CHECK(callContractFunction("f(uint)", 0), encodeArgs()); + ABI_CHECK(callContractFunction("g(uint)", 0), encodeArgs()); ABI_CHECK(callContractFunction("h()"), encodeArgs(2)); } diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 293f5f44..9847ecae 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -4920,20 +4920,6 @@ BOOST_AUTO_TEST_CASE(integer_and_fixed_interaction) CHECK_SUCCESS(text); } -BOOST_AUTO_TEST_CASE(signed_rational_modulus) -{ - char const* text = R"( - contract test { - function f() public { - fixed a = 0.42578125 % -0.4271087646484375; - fixed b = .5 % a; - fixed c = a % b; - } - } - )"; - CHECK_SUCCESS(text); -} - BOOST_AUTO_TEST_CASE(one_divided_by_three_integer_conversion) { char const* text = R"( diff --git a/test/libsolidity/syntaxTests/constants/addmod_mulmod_rational.sol b/test/libsolidity/syntaxTests/constants/addmod_mulmod_rational.sol new file mode 100644 index 00000000..26712735 --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/addmod_mulmod_rational.sol @@ -0,0 +1,7 @@ +contract C { + uint constant a = addmod(3, 4, 0.1); + uint constant b = mulmod(3, 4, 0.1); +} +// ---- +// TypeError: (48-51): Invalid type for argument in function call. Invalid implicit conversion from rational_const 1 / 10 to uint256 requested. +// TypeError: (89-92): Invalid type for argument in function call. Invalid implicit conversion from rational_const 1 / 10 to uint256 requested. diff --git a/test/libsolidity/syntaxTests/constants/addmod_zero.sol b/test/libsolidity/syntaxTests/constants/addmod_zero.sol new file mode 100644 index 00000000..18f7d64a --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/addmod_zero.sol @@ -0,0 +1,11 @@ +contract c { + uint constant a1 = 0; + uint constant a2 = 1; + uint constant b1 = addmod(3, 4, 0); + uint constant b2 = addmod(3, 4, a1); + uint constant b3 = addmod(3, 4, a2 - 1); +} +// ---- +// TypeError: (88-103): Arithmetic modulo zero. +// TypeError: (128-144): Arithmetic modulo zero. +// TypeError: (169-189): Arithmetic modulo zero. diff --git a/test/libsolidity/syntaxTests/constants/division_by_zero.sol b/test/libsolidity/syntaxTests/constants/division_by_zero.sol new file mode 100644 index 00000000..bf6000ec --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/division_by_zero.sol @@ -0,0 +1,9 @@ +contract c { + uint constant a1 = 0; + uint constant a2 = 1; + uint constant b1 = 7 / a1; + uint constant b2 = 7 / (a2 - 1); +} +// ---- +// TypeError: (88-94): Division by zero. +// TypeError: (119-131): Division by zero. diff --git a/test/libsolidity/syntaxTests/constants/mod_div_rational.sol b/test/libsolidity/syntaxTests/constants/mod_div_rational.sol new file mode 100644 index 00000000..f8b6ce31 --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/mod_div_rational.sol @@ -0,0 +1,6 @@ +contract C { + fixed a1 = 0.1 % -0.4271087646484375; + fixed a2 = 0.1 % 0.4271087646484375; + fixed a3 = 0 / 0.123; + fixed a4 = 0 / -0.123; +} diff --git a/test/libsolidity/syntaxTests/constants/mod_zero.sol b/test/libsolidity/syntaxTests/constants/mod_zero.sol new file mode 100644 index 00000000..f5e4a23a --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/mod_zero.sol @@ -0,0 +1,9 @@ +contract c { + uint constant a1 = 0; + uint constant a2 = 1; + uint constant b1 = 3 % a1; + uint constant b2 = 3 % (a2 - 1); +} +// ---- +// TypeError: (88-94): Modulo zero. +// TypeError: (119-131): Modulo zero. diff --git a/test/libsolidity/syntaxTests/constants/mulmod_zero.sol b/test/libsolidity/syntaxTests/constants/mulmod_zero.sol new file mode 100644 index 00000000..856d01eb --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/mulmod_zero.sol @@ -0,0 +1,11 @@ +contract c { + uint constant a1 = 0; + uint constant a2 = 1; + uint constant b1 = mulmod(3, 4, 0); + uint constant b2 = mulmod(3, 4, a1); + uint constant b3 = mulmod(3, 4, a2 - 1); +} +// ---- +// TypeError: (88-103): Arithmetic modulo zero. +// TypeError: (128-144): Arithmetic modulo zero. +// TypeError: (169-189): Arithmetic modulo zero. diff --git a/test/libsolidity/syntaxTests/signed_rational_modulus.sol b/test/libsolidity/syntaxTests/signed_rational_modulus.sol new file mode 100644 index 00000000..b37d33d0 --- /dev/null +++ b/test/libsolidity/syntaxTests/signed_rational_modulus.sol @@ -0,0 +1,8 @@ +contract test { + function f() public pure { + fixed a = 0.42578125 % -0.4271087646484375; + fixed b = .5 % a; + fixed c = a % b; + a; b; c; + } +} |