diff options
-rw-r--r-- | Changelog.md | 2 | ||||
-rw-r--r-- | docs/assembly.rst | 6 | ||||
-rw-r--r-- | libsolidity/analysis/TypeChecker.cpp | 5 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmParser.cpp | 13 | ||||
-rw-r--r-- | test/libsolidity/InlineAssembly.cpp | 12 | ||||
-rw-r--r-- | test/libsolidity/SolidityNameAndTypeResolution.cpp | 15 |
6 files changed, 45 insertions, 8 deletions
diff --git a/Changelog.md b/Changelog.md index 83134ee7..eed7e258 100644 --- a/Changelog.md +++ b/Changelog.md @@ -9,7 +9,9 @@ Features: * Inline Assembly: introduce ``keccak256`` as an opcode. ``sha3`` is still a valid alias. Bugfixes: + * Fixed crash concerning non-callable types. * Unused variable warnings no longer issued for variables used inside inline assembly. + * Inline Assembly: Enforce function arguments when parsing functional instructions. ### 0.4.11 (2017-05-03) diff --git a/docs/assembly.rst b/docs/assembly.rst index 938b72fa..394fc9f5 100644 --- a/docs/assembly.rst +++ b/docs/assembly.rst @@ -325,8 +325,10 @@ would be written as follows mstore(0x80, add(mload(0x80), 3)) -Functional style and instructional style can be mixed, but any opcode inside a -functional style expression has to return exactly one stack slot (most of the opcodes do). +Functional style expressions cannot use instructional style internally, i.e. +``1 2 mstore(0x80, add)`` is not valid assembly, it has to be written as +``mstore(0x80, add(2, 1))``. For opcodes that do not take arguments, the +parentheses can be omitted. Note that the order of arguments is reversed in functional-style as opposed to the instruction-style way. If you use functional-style, the first argument will end up on the stack top. diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index b1911ef0..2a8d1ff6 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1287,14 +1287,11 @@ bool TypeChecker::visit(FunctionCall const& _functionCall) membersRemovedForStructConstructor = structType.membersMissingInMemory(); _functionCall.annotation().isPure = isPure; } - else - { - functionType = dynamic_pointer_cast<FunctionType const>(expressionType); + else if ((functionType = dynamic_pointer_cast<FunctionType const>(expressionType))) _functionCall.annotation().isPure = isPure && _functionCall.expression().annotation().isPure && functionType->isPure(); - } if (!functionType) { diff --git a/libsolidity/inlineasm/AsmParser.cpp b/libsolidity/inlineasm/AsmParser.cpp index 68a9cb03..f9b073ba 100644 --- a/libsolidity/inlineasm/AsmParser.cpp +++ b/libsolidity/inlineasm/AsmParser.cpp @@ -174,6 +174,19 @@ assembly::Case Parser::parseCase() assembly::Statement Parser::parseExpression() { Statement operation = parseElementaryOperation(true); + if (operation.type() == typeid(Instruction)) + { + Instruction const& instr = boost::get<Instruction>(operation); + int args = instructionInfo(instr.instruction).args; + if (args > 0 && currentToken() != Token::LParen) + fatalParserError(string( + "Expected token \"(\" (\"" + + instructionNames().at(instr.instruction) + + "\" expects " + + boost::lexical_cast<string>(args) + + " arguments)" + )); + } if (currentToken() == Token::LParen) return parseCall(std::move(operation)); else diff --git a/test/libsolidity/InlineAssembly.cpp b/test/libsolidity/InlineAssembly.cpp index 276f7bb5..aae6dacd 100644 --- a/test/libsolidity/InlineAssembly.cpp +++ b/test/libsolidity/InlineAssembly.cpp @@ -213,6 +213,16 @@ BOOST_AUTO_TEST_CASE(functional) BOOST_CHECK(successParse("{ let x := 2 add(7, mul(6, x)) mul(7, 8) add =: x }")); } +BOOST_AUTO_TEST_CASE(functional_partial) +{ + CHECK_PARSE_ERROR("{ let x := byte }", ParserError, "Expected token \"(\""); +} + +BOOST_AUTO_TEST_CASE(functional_partial_success) +{ + BOOST_CHECK(successParse("{ let x := byte(1, 2) }")); +} + BOOST_AUTO_TEST_CASE(functional_assignment) { BOOST_CHECK(successParse("{ let x := 2 x := 7 }")); @@ -258,7 +268,7 @@ BOOST_AUTO_TEST_CASE(switch_duplicate_case) BOOST_AUTO_TEST_CASE(switch_invalid_expression) { CHECK_PARSE_ERROR("{ switch {} default {} }", ParserError, "Literal, identifier or instruction expected."); - CHECK_PARSE_ERROR("{ 1 2 switch mul default {} }", ParserError, "Instructions are not supported as expressions for switch."); + CHECK_PARSE_ERROR("{ switch calldatasize default {} }", ParserError, "Instructions are not supported as expressions for switch."); } BOOST_AUTO_TEST_CASE(switch_default_before_case) diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 017eeaec..70934543 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -5785,6 +5785,20 @@ BOOST_AUTO_TEST_CASE(no_unused_inline_asm) CHECK_SUCCESS_NO_WARNINGS(text); } +BOOST_AUTO_TEST_CASE(callable_crash) +{ + char const* text = R"( + contract C { + struct S { uint a; bool x; } + S public s; + function C() { + 3({a: 1, x: true}); + } + } + )"; + CHECK_ERROR(text, TypeError, "Type is not callable"); +} + BOOST_AUTO_TEST_CASE(returndatacopy_as_variable) { char const* text = R"( @@ -5810,7 +5824,6 @@ BOOST_AUTO_TEST_CASE(shadowing_warning_can_be_removed) } - BOOST_AUTO_TEST_SUITE_END() } |