diff options
22 files changed, 365 insertions, 56 deletions
diff --git a/Changelog.md b/Changelog.md index 81c8b974..8a315685 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,14 +1,18 @@ -### 0.4.22 (unreleased) +### 0.4.22 (2018-04-16) Features: * Code Generator: Initialize arrays without using ``msize()``. * Code Generator: More specialized and thus optimized implementation for ``x.push(...)`` * Commandline interface: Error when missing or inaccessible file detected. Suppress it with the ``--ignore-missing`` flag. * Constant Evaluator: Fix evaluation of single element tuples. + * General: Add encoding routines ``abi.encodePacked``, ``abi.encode``, ``abi.encodeWithSelector`` and ``abi.encodeWithSignature``. + * General: Add global function ``gasleft()`` and deprecate ``msg.gas``. + * General: Add global function ``blockhash(uint)`` and deprecate ``block.hash(uint)``. * General: Allow providing reason string for ``revert()`` and ``require()``. * General: Limit the number of errors output in a single run to 256. * General: Support accessing dynamic return data in post-byzantium EVMs. - * General: Add encoding routines ``abi.encodePacked``, ``abi.encode``, ``abi.encodeWithSelector`` and ``abi.encodeWithSignature``. + * Inheritance: Error when using empty parentheses for base class constructors that require arguments as experimental 0.5.0 feature. + * Inheritance: Error when using no parentheses in modifier-style constructor calls as experimental 0.5.0 feature. * Interfaces: Allow overriding external functions in interfaces with public in an implementing contract. * Optimizer: Optimize ``SHL`` and ``SHR`` only involving constants (Constantinople only). * Optimizer: Remove useless ``SWAP1`` instruction preceding a commutative instruction (such as ``ADD``, ``MUL``, etc). @@ -18,9 +22,9 @@ Features: * Syntax Checker: Issue warning for empty structs (or error as experimental 0.5.0 feature). * Syntax Checker: Warn about modifiers on functions without implementation (this will turn into an error with version 0.5.0). * Syntax Tests: Add source locations to syntax test expectations. + * Type Checker: Improve documentation and warnings for accessing contract members inherited from ``address``. * General: Introduce new constructor syntax using the ``constructor`` keyword as experimental 0.5.0 feature. - * Inheritance: Error when using empty parentheses for base class constructors that require arguments as experimental 0.5.0 feature. - * Inheritance: Error when using no parentheses in modifier-style constructor calls as experimental 0.5.0 feature. + Bugfixes: * Code Generator: Allow ``block.blockhash`` without being called. @@ -29,6 +33,7 @@ Bugfixes: * Code Generator: Bugfix in modifier lookup in libraries. * Code Generator: Implement packed encoding of external function types. * Code Generator: Treat empty base constructor argument list as not provided. + * Code Generator: Properly force-clean bytesXX types for shortening conversions. * Commandline interface: Fix error messages for imported files that do not exist. * Commandline interface: Support ``--evm-version constantinople`` properly. * DocString Parser: Fix error message for empty descriptions. @@ -37,13 +42,14 @@ Bugfixes: * Parser: Fix internal compiler error when parsing ``var`` declaration without identifier. * Parser: Fix parsing of getters for function type variables. * Standard JSON: Support ``constantinople`` as ``evmVersion`` properly. + * Static Analyzer: Fix non-deterministic order of unused variable warnings. + * Static Analyzer: Invalid arithmetic with constant expressions causes errors. * Type Checker: Fix detection of recursive structs. * Type Checker: Fix asymmetry bug when comparing with literal numbers. * Type System: Improve error message when attempting to shift by a fractional amount. * 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. + * Type System: Restrict rational numbers to 4096 bits. ### 0.4.21 (2018-03-07) diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index 233ac22a..cc2f8711 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -34,13 +34,6 @@ endif() set(ETH_CMAKE_DIR ${CMAKE_CURRENT_LIST_DIR}) set(ETH_SCRIPTS_DIR ${ETH_CMAKE_DIR}/scripts) -find_program(CTEST_COMMAND ctest) - -#message(STATUS "CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH}") -#message(STATUS "CMake Helper Path: ${ETH_CMAKE_DIR}") -#message(STATUS "CMake Script Path: ${ETH_SCRIPTS_DIR}") -#message(STATUS "ctest path: ${CTEST_COMMAND}") - ## use multithreaded boost libraries, with -mt suffix set(Boost_USE_MULTITHREADED ON) option(Boost_USE_STATIC_LIBS "Link Boost statically" ON) diff --git a/docs/assembly.rst b/docs/assembly.rst index 705cd1b8..978e71e3 100644 --- a/docs/assembly.rst +++ b/docs/assembly.rst @@ -405,6 +405,16 @@ changes during the call, and thus references to local variables will be wrong. } } +.. note:: + If you access variables of a type that spans less than 256 bits + (for example ``uint64``, ``address``, ``bytes16`` or ``byte``), + you cannot make any assumptions about bits not part of the + encoding of the type. Especially, do not assume them to be zero. + To be safe, always clear the data properly before you use it + in a context where this is important: + ``uint32 x = f(); assembly { x := and(x, 0xffffffff) /* now use x */ }`` + To clean signed types, you can use the ``signextend`` opcode. + Labels ------ diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json index 4c976a32..32f305c8 100644 --- a/docs/bugs_by_version.json +++ b/docs/bugs_by_version.json @@ -422,6 +422,10 @@ "bugs": [], "released": "2018-03-07" }, + "0.4.22": { + "bugs": [], + "released": "2018-04-16" + }, "0.4.3": { "bugs": [ "ZeroFunctionSelector", diff --git a/docs/contracts.rst b/docs/contracts.rst index dfd2e8a6..a1f2895c 100644 --- a/docs/contracts.rst +++ b/docs/contracts.rst @@ -40,7 +40,7 @@ This means that cyclic creation dependencies are impossible. :: - pragma solidity >0.4.21; + pragma solidity ^0.4.22; contract OwnedToken { // TokenCreator is a contract type that is defined below. @@ -989,7 +989,7 @@ default constructor: ``contructor() public {}``. :: - pragma solidity >0.4.21; + pragma solidity ^0.4.22; contract A { uint public a; diff --git a/docs/types.rst b/docs/types.rst index be8afe48..5c20dc67 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -179,8 +179,8 @@ All three functions ``call``, ``delegatecall`` and ``callcode`` are very low-lev The ``.gas()`` option is available on all three methods, while the ``.value()`` option is not supported for ``delegatecall``. .. note:: - All contracts inherit the members of address, so it is possible to query the balance of the - current contract using ``this.balance``. + All contracts can be converted to ``address`` type, so it is possible to query the balance of the + current contract using ``address(this).balance``. .. note:: The use of ``callcode`` is discouraged and will be removed in the future. diff --git a/libdevcore/CMakeLists.txt b/libdevcore/CMakeLists.txt index d107f701..fa7e3f48 100644 --- a/libdevcore/CMakeLists.txt +++ b/libdevcore/CMakeLists.txt @@ -2,9 +2,7 @@ file(GLOB sources "*.cpp") file(GLOB headers "*.h") add_library(devcore ${sources} ${headers}) -target_link_libraries(devcore PRIVATE ${JSONCPP_LIBRARY} ${Boost_FILESYSTEM_LIBRARIES} ${Boost_REGEX_LIBRARIES} ${Boost_SYSTEM_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) -target_include_directories(devcore SYSTEM PUBLIC ${Boost_INCLUDE_DIRS}) +target_link_libraries(devcore PRIVATE jsoncpp ${Boost_FILESYSTEM_LIBRARIES} ${Boost_REGEX_LIBRARIES} ${Boost_SYSTEM_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) target_include_directories(devcore PUBLIC "${CMAKE_SOURCE_DIR}") -target_include_directories(devcore PUBLIC "${JSONCPP_INCLUDE_DIR}") -add_dependencies(devcore jsoncpp) +target_include_directories(devcore SYSTEM PUBLIC ${Boost_INCLUDE_DIRS}) add_dependencies(devcore solidity_BuildInfo.h) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index f4df4c94..47a551dc 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1988,7 +1988,8 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) m_errorReporter.warning( _memberAccess.location(), "Using contract member \"" + memberName +"\" inherited from the address type is deprecated." + - " Convert the contract to \"address\" type to access the member." + " Convert the contract to \"address\" type to access the member," + " for example use \"address(contract)." + memberName + "\" instead." ); } diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 68b12777..51739cb0 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -44,6 +44,85 @@ using namespace std; using namespace dev; using namespace dev::solidity; +namespace +{ + +unsigned int mostSignificantBit(bigint const& _number) +{ +#if BOOST_VERSION < 105500 + solAssert(_number > 0, ""); + bigint number = _number; + unsigned int result = 0; + while (number != 0) + { + number >>= 1; + ++result; + } + return --result; +#else + return boost::multiprecision::msb(_number); +#endif +} + +/// Check whether (_base ** _exp) fits into 4096 bits. +bool fitsPrecisionExp(bigint const& _base, bigint const& _exp) +{ + if (_base == 0) + return true; + + solAssert(_base > 0, ""); + + size_t const bitsMax = 4096; + + unsigned mostSignificantBaseBit = mostSignificantBit(_base); + if (mostSignificantBaseBit == 0) // _base == 1 + return true; + if (mostSignificantBaseBit > bitsMax) // _base >= 2 ^ 4096 + return false; + + bigint bitsNeeded = _exp * (mostSignificantBaseBit + 1); + + return bitsNeeded <= bitsMax; +} + +/// Checks whether _mantissa * (X ** _exp) fits into 4096 bits, +/// where X is given indirectly via _log2OfBase = log2(X). +bool fitsPrecisionBaseX( + bigint const& _mantissa, + double _log2OfBase, + uint32_t _exp +) +{ + if (_mantissa == 0) + return true; + + solAssert(_mantissa > 0, ""); + + size_t const bitsMax = 4096; + + unsigned mostSignificantMantissaBit = mostSignificantBit(_mantissa); + if (mostSignificantMantissaBit > bitsMax) // _mantissa >= 2 ^ 4096 + return false; + + bigint bitsNeeded = mostSignificantMantissaBit + bigint(floor(double(_exp) * _log2OfBase)) + 1; + return bitsNeeded <= bitsMax; +} + +/// Checks whether _mantissa * (10 ** _expBase10) fits into 4096 bits. +bool fitsPrecisionBase10(bigint const& _mantissa, uint32_t _expBase10) +{ + double const log2Of10AwayFromZero = 3.3219280948873624; + return fitsPrecisionBaseX(_mantissa, log2Of10AwayFromZero, _expBase10); +} + +/// Checks whether _mantissa * (2 ** _expBase10) fits into 4096 bits. +bool fitsPrecisionBase2(bigint const& _mantissa, uint32_t _expBase2) +{ + return fitsPrecisionBaseX(_mantissa, 1.0, _expBase2); +} + +} + void StorageOffsets::computeOffsets(TypePointers const& _types) { bigint slotOffset = 0; @@ -689,31 +768,39 @@ tuple<bool, rational> RationalNumberType::isValidLiteral(Literal const& _literal } else if (expPoint != _literal.value().end()) { - // parse the exponent + // Parse base and exponent. Checks numeric limit. bigint exp = bigint(string(expPoint + 1, _literal.value().end())); if (exp > numeric_limits<int32_t>::max() || exp < numeric_limits<int32_t>::min()) return make_tuple(false, rational(0)); - // parse the base + uint32_t expAbs = bigint(abs(exp)).convert_to<uint32_t>(); + + tuple<bool, rational> base = parseRational(string(_literal.value().begin(), expPoint)); + if (!get<0>(base)) return make_tuple(false, rational(0)); value = get<1>(base); if (exp < 0) { - exp *= -1; + if (!fitsPrecisionBase10(abs(value.denominator()), expAbs)) + return make_tuple(false, rational(0)); value /= boost::multiprecision::pow( bigint(10), - exp.convert_to<int32_t>() + expAbs ); } - else + else if (exp > 0) + { + if (!fitsPrecisionBase10(abs(value.numerator()), expAbs)) + return make_tuple(false, rational(0)); value *= boost::multiprecision::pow( bigint(10), - exp.convert_to<int32_t>() + expAbs ); + } } else { @@ -912,16 +999,49 @@ TypePointer RationalNumberType::binaryOperatorResult(Token::Value _operator, Typ using boost::multiprecision::pow; if (other.isFractional()) return TypePointer(); - else if (abs(other.m_value) > numeric_limits<uint32_t>::max()) - return TypePointer(); // This will need too much memory to represent. - uint32_t exponent = abs(other.m_value).numerator().convert_to<uint32_t>(); - bigint numerator = pow(m_value.numerator(), exponent); - bigint denominator = pow(m_value.denominator(), exponent); - if (other.m_value >= 0) - value = rational(numerator, denominator); + solAssert(other.m_value.denominator() == 1, ""); + bigint const& exp = other.m_value.numerator(); + + // x ** 0 = 1 + // for 0, 1 and -1 the size of the exponent doesn't have to be restricted + if (exp == 0) + value = 1; + else if (m_value.numerator() == 0 || m_value == 1) + value = m_value; + else if (m_value == -1) + { + bigint isOdd = abs(exp) & bigint(1); + value = 1 - 2 * isOdd.convert_to<int>(); + } else - // invert - value = rational(denominator, numerator); + { + if (abs(exp) > numeric_limits<uint32_t>::max()) + return TypePointer(); // This will need too much memory to represent. + + uint32_t absExp = bigint(abs(exp)).convert_to<uint32_t>(); + + // Limit size to 4096 bits + if (!fitsPrecisionExp(abs(m_value.numerator()), absExp) || !fitsPrecisionExp(abs(m_value.denominator()), absExp)) + return TypePointer(); + + static auto const optimizedPow = [](bigint const& _base, uint32_t _exponent) -> bigint { + if (_base == 1) + return 1; + else if (_base == -1) + return 1 - 2 * int(_exponent & 1); + else + return pow(_base, _exponent); + }; + + bigint numerator = optimizedPow(m_value.numerator(), absExp); + bigint denominator = optimizedPow(m_value.denominator(), absExp); + + if (exp >= 0) + value = rational(numerator, denominator); + else + // invert + value = rational(denominator, numerator); + } break; } case Token::SHL: @@ -933,28 +1053,48 @@ TypePointer RationalNumberType::binaryOperatorResult(Token::Value _operator, Typ return TypePointer(); else if (other.m_value > numeric_limits<uint32_t>::max()) return TypePointer(); - uint32_t exponent = other.m_value.numerator().convert_to<uint32_t>(); - value = m_value.numerator() * pow(bigint(2), exponent); + if (m_value.numerator() == 0) + value = 0; + else + { + uint32_t exponent = other.m_value.numerator().convert_to<uint32_t>(); + if (!fitsPrecisionBase2(abs(m_value.numerator()), exponent)) + return TypePointer(); + value = m_value.numerator() * pow(bigint(2), exponent); + } break; } // NOTE: we're using >> (SAR) to denote right shifting. The type of the LValue // determines the resulting type and the type of shift (SAR or SHR). case Token::SAR: { - using boost::multiprecision::pow; + namespace mp = boost::multiprecision; if (fractional) return TypePointer(); else if (other.m_value < 0) return TypePointer(); else if (other.m_value > numeric_limits<uint32_t>::max()) return TypePointer(); - uint32_t exponent = other.m_value.numerator().convert_to<uint32_t>(); - value = rational(m_value.numerator() / pow(bigint(2), exponent), 1); + if (m_value.numerator() == 0) + value = 0; + else + { + uint32_t exponent = other.m_value.numerator().convert_to<uint32_t>(); + if (exponent > mostSignificantBit(mp::abs(m_value.numerator()))) + value = 0; + else + value = rational(m_value.numerator() / mp::pow(bigint(2), exponent), 1); + } break; } default: return TypePointer(); } + + // verify that numerator and denominator fit into 4096 bit after every operation + if (value.numerator() != 0 && max(mostSignificantBit(abs(value.numerator())), mostSignificantBit(abs(value.denominator()))) > 4096) + return TypePointer(); + return make_shared<RationalNumberType>(value); } } diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index b4550153..4af7d905 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -684,19 +684,17 @@ void CompilerUtils::convertType( // clear for conversion to longer bytes solAssert(targetTypeCategory == Type::Category::FixedBytes, "Invalid type conversion requested."); FixedBytesType const& targetType = dynamic_cast<FixedBytesType const&>(_targetType); - if (targetType.numBytes() > typeOnStack.numBytes() || _cleanupNeeded) + if (typeOnStack.numBytes() == 0 || targetType.numBytes() == 0) + m_context << Instruction::POP << u256(0); + else if (targetType.numBytes() > typeOnStack.numBytes() || _cleanupNeeded) { - if (typeOnStack.numBytes() == 0) - m_context << Instruction::POP << u256(0); - else - { - m_context << ((u256(1) << (256 - typeOnStack.numBytes() * 8)) - 1); - m_context << Instruction::NOT << Instruction::AND; - } + int bytes = min(typeOnStack.numBytes(), targetType.numBytes()); + m_context << ((u256(1) << (256 - bytes * 8)) - 1); + m_context << Instruction::NOT << Instruction::AND; } } - } break; + } case Type::Category::Enum: solAssert(_targetType == _typeOnStack || targetTypeCategory == Type::Category::Integer, ""); if (enumOverflowCheckPending) @@ -798,8 +796,9 @@ void CompilerUtils::convertType( bytesConstRef data(value); if (targetTypeCategory == Type::Category::FixedBytes) { + int const numBytes = dynamic_cast<FixedBytesType const&>(_targetType).numBytes(); solAssert(data.size() <= 32, ""); - m_context << h256::Arith(h256(data, h256::AlignLeft)); + m_context << (h256::Arith(h256(data, h256::AlignLeft)) & (~(u256(-1) >> (8 * numBytes)))); } else if (targetTypeCategory == Type::Category::Array) { diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index ed5af42e..3cf46a9d 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -1023,7 +1023,6 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) solAssert(function.kind() == FunctionType::Kind::ABIEncodeWithSelector, ""); } - // Cleanup actually does not clean on shrinking the type. utils().convertType(*dataOnStack, FixedBytesType(4), true); // stack: <memory pointer> <selector> @@ -1034,7 +1033,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) let data_start := add(mem_ptr, 0x20) let data := mload(data_start) let mask := )" + mask + R"( - mstore(data_start, or(and(data, mask), and(selector, not(mask)))) + mstore(data_start, or(and(data, mask), selector)) })", {"mem_ptr", "selector"}); m_context << Instruction::POP; } diff --git a/std/StandardToken.sol b/std/StandardToken.sol index 5afc9747..ca0658f2 100644 --- a/std/StandardToken.sol +++ b/std/StandardToken.sol @@ -1,4 +1,4 @@ -pragma solidity >0.4.21; +pragma solidity ^0.4.22; import "./Token.sol"; diff --git a/std/owned.sol b/std/owned.sol index 8e1d5917..75007f3e 100644 --- a/std/owned.sol +++ b/std/owned.sol @@ -1,4 +1,4 @@ -pragma solidity >0.4.21; +pragma solidity ^0.4.22; contract owned { address owner; diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index cbeca215..789b89d1 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -102,6 +102,29 @@ BOOST_AUTO_TEST_CASE(exp_operator_const_signed) ABI_CHECK(callContractFunction("f()", bytes()), toBigEndian(u256(-8))); } +BOOST_AUTO_TEST_CASE(exp_zero) +{ + char const* sourceCode = R"( + contract test { + function f(uint a) returns(uint d) { return a ** 0; } + } + )"; + compileAndRun(sourceCode); + testContractAgainstCppOnRange("f(uint256)", [](u256 const&) -> u256 { return u256(1); }, 0, 16); +} + +BOOST_AUTO_TEST_CASE(exp_zero_literal) +{ + char const* sourceCode = R"( + contract test { + function f() returns(uint d) { return 0 ** 0; } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("f()", bytes()), toBigEndian(u256(1))); +} + + BOOST_AUTO_TEST_CASE(conditional_expression_true_literal) { char const* sourceCode = R"( @@ -8807,6 +8830,24 @@ BOOST_AUTO_TEST_CASE(cleanup_bytes_types) ABI_CHECK(callContractFunction("f(bytes2,uint16)", string("abc"), u256(0x040102)), encodeArgs(0)); } +BOOST_AUTO_TEST_CASE(cleanup_bytes_types_shortening) +{ + char const* sourceCode = R"( + contract C { + function f() pure returns (bytes32 r) { + bytes4 x = 0xffffffff; + bytes2 y = bytes2(x); + assembly { r := y } + // At this point, r and y both store four bytes, but + // y is properly cleaned before the equality check + require(y == bytes2(0xffff)); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("f()"), encodeArgs("\xff\xff\xff\xff")); +} + BOOST_AUTO_TEST_CASE(skip_dynamic_types) { // The EVM cannot provide access to dynamically-sized return values, so we have to skip them. @@ -11322,6 +11363,10 @@ BOOST_AUTO_TEST_CASE(abi_encode) y[0] = "e"; require(y[0] == "e"); } + function f4() returns (bytes) { + bytes4 x = "abcd"; + return abi.encode(bytes2(x)); + } } )"; compileAndRun(sourceCode, 0, "C"); @@ -11329,6 +11374,7 @@ BOOST_AUTO_TEST_CASE(abi_encode) ABI_CHECK(callContractFunction("f1()"), encodeArgs(0x20, 0x40, 1, 2)); ABI_CHECK(callContractFunction("f2()"), encodeArgs(0x20, 0xa0, 1, 0x60, 2, 3, "abc")); ABI_CHECK(callContractFunction("f3()"), encodeArgs(0x20, 0xa0, 1, 0x60, 2, 3, "abc")); + ABI_CHECK(callContractFunction("f4()"), encodeArgs(0x20, 0x20, "ab")); } BOOST_AUTO_TEST_CASE(abi_encode_v2) diff --git a/test/libsolidity/syntaxTests/types/rational_number_array_index_limit.sol b/test/libsolidity/syntaxTests/types/rational_number_array_index_limit.sol new file mode 100644 index 00000000..45ede998 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/rational_number_array_index_limit.sol @@ -0,0 +1,5 @@ +contract c { + uint[2**253] data; +} +// ---- +// Warning: (17-34): Variable covers a large part of storage and thus makes collisions likely. Either use mappings or dynamic arrays and allow their size to be increased only in small quantities per transaction. diff --git a/test/libsolidity/syntaxTests/types/rational_number_bitshift_limit.sol b/test/libsolidity/syntaxTests/types/rational_number_bitshift_limit.sol new file mode 100644 index 00000000..94981aa0 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/rational_number_bitshift_limit.sol @@ -0,0 +1,13 @@ +contract c { + function f() public pure { + int a; + a = 1 << 4095; // shift is fine, but result too large + a = 1 << 4096; // too large + a = (1E1233) << 2; // too large + } +} +// ---- +// TypeError: (71-80): Type int_const 5221...(1225 digits omitted)...5168 is not implicitly convertible to expected type int256. +// TypeError: (133-142): Operator << not compatible with types int_const 1 and int_const 4096 +// TypeError: (169-182): Operator << not compatible with types int_const 1000...(1226 digits omitted)...0000 and int_const 2 +// TypeError: (169-182): Type int_const 1000...(1226 digits omitted)...0000 is not implicitly convertible to expected type int256. diff --git a/test/libsolidity/syntaxTests/types/rational_number_div_limit.sol b/test/libsolidity/syntaxTests/types/rational_number_div_limit.sol new file mode 100644 index 00000000..1b0b5f94 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/rational_number_div_limit.sol @@ -0,0 +1,9 @@ +contract c { + function f() public pure { + int a; + a = 1/(2<<4094)/(2<<4094); + } +} +// ---- +// TypeError: (71-92): Operator / not compatible with types rational_const 1 / 5221...(1225 digits omitted)...5168 and int_const 5221...(1225 digits omitted)...5168 +// TypeError: (71-92): Type rational_const 1 / 5221...(1225 digits omitted)...5168 is not implicitly convertible to expected type int256. Try converting to type ufixed8x80 or use an explicit conversion. diff --git a/test/libsolidity/syntaxTests/types/rational_number_exp_limit.sol b/test/libsolidity/syntaxTests/types/rational_number_exp_limit.sol new file mode 100644 index 00000000..6785f580 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/rational_number_exp_limit.sol @@ -0,0 +1,50 @@ +contract c { + function f() public pure { + int a; + a = 4 ** 4 ** 2 ** 4 ** 4 ** 4 ** 4; + a = -4 ** 4 ** 2 ** 4 ** 4 ** 4 ** 4 ** 4; + a = 4 ** (-(2 ** 4 ** 4 ** 4 ** 4 ** 4)); + a = 0 ** 1E1233; // fine + a = 1 ** 1E1233; // fine + a = -1 ** 1E1233; // fine + a = 2 ** 1E1233; + a = -2 ** 1E1233; + a = 2 ** -1E1233; + a = -2 ** -1E1233; + a = 1E1233 ** 2; + a = -1E1233 ** 2; + a = 1E1233 ** -2; + a = -1E1233 ** -2; + a = 1E1233 ** 1E1233; + a = 1E1233 ** -1E1233; + a = -1E1233 ** 1E1233; + a = -1E1233 ** -1E1233; + } +} +// ---- +// TypeError: (71-102): Operator ** not compatible with types int_const 1797...(301 digits omitted)...7216 and int_const 4 +// TypeError: (71-102): Type int_const 1797...(301 digits omitted)...7216 is not implicitly convertible to expected type int256. +// TypeError: (116-148): Operator ** not compatible with types int_const 1797...(301 digits omitted)...7216 and int_const 4 +// TypeError: (116-153): Operator ** not compatible with types int_const 1797...(301 digits omitted)...7216 and int_const 4 +// TypeError: (116-153): Type int_const 1797...(301 digits omitted)...7216 is not implicitly convertible to expected type int256. +// TypeError: (167-203): Operator ** not compatible with types int_const 4 and int_const -179...(302 digits omitted)...7216 +// TypeError: (317-328): Operator ** not compatible with types int_const 2 and int_const 1000...(1226 digits omitted)...0000 +// TypeError: (342-354): Operator ** not compatible with types int_const -2 and int_const 1000...(1226 digits omitted)...0000 +// TypeError: (368-380): Operator ** not compatible with types int_const 2 and int_const -100...(1227 digits omitted)...0000 +// TypeError: (394-407): Operator ** not compatible with types int_const -2 and int_const -100...(1227 digits omitted)...0000 +// TypeError: (421-432): Operator ** not compatible with types int_const 1000...(1226 digits omitted)...0000 and int_const 2 +// TypeError: (421-432): Type int_const 1000...(1226 digits omitted)...0000 is not implicitly convertible to expected type int256. +// TypeError: (446-458): Operator ** not compatible with types int_const -100...(1227 digits omitted)...0000 and int_const 2 +// TypeError: (446-458): Type int_const -100...(1227 digits omitted)...0000 is not implicitly convertible to expected type int256. +// TypeError: (472-484): Operator ** not compatible with types int_const 1000...(1226 digits omitted)...0000 and int_const -2 +// TypeError: (472-484): Type int_const 1000...(1226 digits omitted)...0000 is not implicitly convertible to expected type int256. +// TypeError: (498-511): Operator ** not compatible with types int_const -100...(1227 digits omitted)...0000 and int_const -2 +// TypeError: (498-511): Type int_const -100...(1227 digits omitted)...0000 is not implicitly convertible to expected type int256. +// TypeError: (525-541): Operator ** not compatible with types int_const 1000...(1226 digits omitted)...0000 and int_const 1000...(1226 digits omitted)...0000 +// TypeError: (525-541): Type int_const 1000...(1226 digits omitted)...0000 is not implicitly convertible to expected type int256. +// TypeError: (555-572): Operator ** not compatible with types int_const 1000...(1226 digits omitted)...0000 and int_const -100...(1227 digits omitted)...0000 +// TypeError: (555-572): Type int_const 1000...(1226 digits omitted)...0000 is not implicitly convertible to expected type int256. +// TypeError: (586-603): Operator ** not compatible with types int_const -100...(1227 digits omitted)...0000 and int_const 1000...(1226 digits omitted)...0000 +// TypeError: (586-603): Type int_const -100...(1227 digits omitted)...0000 is not implicitly convertible to expected type int256. +// TypeError: (617-635): Operator ** not compatible with types int_const -100...(1227 digits omitted)...0000 and int_const -100...(1227 digits omitted)...0000 +// TypeError: (617-635): Type int_const -100...(1227 digits omitted)...0000 is not implicitly convertible to expected type int256. diff --git a/test/libsolidity/syntaxTests/types/rational_number_literal_limit_1.sol b/test/libsolidity/syntaxTests/types/rational_number_literal_limit_1.sol new file mode 100644 index 00000000..233857a3 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/rational_number_literal_limit_1.sol @@ -0,0 +1,9 @@ +contract c { + function bignum() public { + uint256 a; + a = 1e1233 / 1e1233; // 1e1233 is still fine + a = 1e1234; // 1e1234 is too big + } +} +// ---- +// TypeError: (128-134): Invalid literal value. diff --git a/test/libsolidity/syntaxTests/types/rational_number_literal_limit_2.sol b/test/libsolidity/syntaxTests/types/rational_number_literal_limit_2.sol new file mode 100644 index 00000000..16673924 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/rational_number_literal_limit_2.sol @@ -0,0 +1,9 @@ +contract c { + function bignum() public { + uint a; + a = 134562324532464234452335168163516E1200 / 134562324532464234452335168163516E1200; // still fine + a = 1345623245324642344523351681635168E1200; // too large + } +} +// ---- +// TypeError: (179-218): Invalid literal value. diff --git a/test/libsolidity/syntaxTests/types/rational_number_literal_limit_3.sol b/test/libsolidity/syntaxTests/types/rational_number_literal_limit_3.sol new file mode 100644 index 00000000..5a696171 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/rational_number_literal_limit_3.sol @@ -0,0 +1,9 @@ +contract c { + function bignum() public { + uint a; + a = 134562324532464.234452335168163517E1200 / 134562324532464.234452335168163517E1200; // still fine + a = 134562324532464.2344523351681635177E1200; // too large + } +} +// ---- +// TypeError: (181-221): Invalid literal value. diff --git a/test/libsolidity/syntaxTests/types/rational_number_mul_limit.sol b/test/libsolidity/syntaxTests/types/rational_number_mul_limit.sol new file mode 100644 index 00000000..bbed94b5 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/rational_number_mul_limit.sol @@ -0,0 +1,9 @@ +contract c { + function f() public pure { + int a; + a = (1<<4095)*(1<<4095); + } +} +// ---- +// TypeError: (71-90): Operator * not compatible with types int_const 5221...(1225 digits omitted)...5168 and int_const 5221...(1225 digits omitted)...5168 +// TypeError: (71-90): Type int_const 5221...(1225 digits omitted)...5168 is not implicitly convertible to expected type int256. |