Skip to content

BREAKING: Require modifiers to contain "_". #836

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 17, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion libsolidity/analysis/SyntaxChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,26 @@ void SyntaxChecker::syntaxError(SourceLocation const& _location, std::string con
m_errors.push_back(err);
}

bool SyntaxChecker::visit(ModifierDefinition const&)
{
m_placeholderFound = false;
return true;
}

void SyntaxChecker::endVisit(ModifierDefinition const& _modifier)
{
if (!m_placeholderFound)
syntaxError(_modifier.body().location(), "Modifier body does not contain '_'.");
m_placeholderFound = false;
}

bool SyntaxChecker::visit(WhileStatement const&)
{
m_inLoopDepth++;
return true;
}

void SyntaxChecker::endVisit(WhileStatement const&)
void SyntaxChecker::endVisit(WhileStatement const& )
{
m_inLoopDepth--;
}
Expand Down Expand Up @@ -78,3 +91,9 @@ bool SyntaxChecker::visit(Break const& _breakStatement)
return true;
}

bool SyntaxChecker::visit(const PlaceholderStatement&)
{
m_placeholderFound = true;
return true;
}

9 changes: 9 additions & 0 deletions libsolidity/analysis/SyntaxChecker.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ namespace solidity
/**
* The module that performs syntax analysis on the AST:
* - whether continue/break is in a for/while loop.
* - whether a modifier contains at least one '_'
*/
class SyntaxChecker: private ASTConstVisitor
{
Expand All @@ -44,6 +45,9 @@ class SyntaxChecker: private ASTConstVisitor
/// Adds a new error to the list of errors.
void syntaxError(SourceLocation const& _location, std::string const& _description);

virtual bool visit(ModifierDefinition const& _modifier) override;
virtual void endVisit(ModifierDefinition const& _modifier) override;

virtual bool visit(WhileStatement const& _whileStatement) override;
virtual void endVisit(WhileStatement const& _whileStatement) override;
virtual bool visit(ForStatement const& _forStatement) override;
Expand All @@ -52,8 +56,13 @@ class SyntaxChecker: private ASTConstVisitor
virtual bool visit(Continue const& _continueStatement) override;
virtual bool visit(Break const& _breakStatement) override;

virtual bool visit(PlaceholderStatement const& _placeholderStatement) override;

ErrorList& m_errors;

/// Flag that indicates whether a function modifier actually contains '_'.
bool m_placeholderFound = false;

int m_inLoopDepth = 0;
};

Expand Down
4 changes: 2 additions & 2 deletions test/libsolidity/SolidityEndToEndTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2410,7 +2410,7 @@ BOOST_AUTO_TEST_CASE(function_modifier_overriding)
modifier mod { _ }
}
contract C is A {
modifier mod { }
modifier mod { if (false) _ }
}
)";
compileAndRun(sourceCode);
Expand All @@ -2427,7 +2427,7 @@ BOOST_AUTO_TEST_CASE(function_modifier_calling_functions_in_creation_context)
function f2() { data |= 0x20; }
function f3() { }
modifier mod1 { f2(); _ }
modifier mod2 { f3(); }
modifier mod2 { f3(); if (false) _ }
function getData() returns (uint r) { return data; }
}
contract C is A {
Expand Down
30 changes: 20 additions & 10 deletions test/libsolidity/SolidityNameAndTypeResolution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -901,35 +901,35 @@ BOOST_AUTO_TEST_CASE(function_modifier_invocation_local_variables)
BOOST_AUTO_TEST_CASE(legal_modifier_override)
{
char const* text = R"(
contract A { modifier mod(uint a) {} }
contract B is A { modifier mod(uint a) {} }
contract A { modifier mod(uint a) { _ } }
contract B is A { modifier mod(uint a) { _ } }
)";
BOOST_CHECK(success(text));
}

BOOST_AUTO_TEST_CASE(illegal_modifier_override)
{
char const* text = R"(
contract A { modifier mod(uint a) {} }
contract B is A { modifier mod(uint8 a) {} }
contract A { modifier mod(uint a) { _ } }
contract B is A { modifier mod(uint8 a) { _ } }
)";
BOOST_CHECK(expectError(text) == Error::Type::TypeError);
}

BOOST_AUTO_TEST_CASE(modifier_overrides_function)
{
char const* text = R"(
contract A { modifier mod(uint a) {} }
contract B is A { function mod(uint a) {} }
contract A { modifier mod(uint a) { _ } }
contract B is A { function mod(uint a) { } }
)";
BOOST_CHECK(expectError(text) == Error::Type::TypeError);
}

BOOST_AUTO_TEST_CASE(function_overrides_modifier)
{
char const* text = R"(
contract A { function mod(uint a) {} }
contract B is A { modifier mod(uint a) {} }
contract A { function mod(uint a) { } }
contract B is A { modifier mod(uint a) { _ } }
)";
BOOST_CHECK(expectError(text) == Error::Type::TypeError);
}
Expand All @@ -938,8 +938,8 @@ BOOST_AUTO_TEST_CASE(modifier_returns_value)
{
char const* text = R"(
contract A {
function f(uint a) mod(2) returns (uint r) {}
modifier mod(uint a) { return 7; }
function f(uint a) mod(2) returns (uint r) { }
modifier mod(uint a) { _ return 7; }
}
)";
BOOST_CHECK(expectError(text) == Error::Type::TypeError);
Expand Down Expand Up @@ -3823,6 +3823,16 @@ BOOST_AUTO_TEST_CASE(unused_return_value_delegatecall)
BOOST_CHECK(expectError(text, true) == Error::Type::Warning);
}

BOOST_AUTO_TEST_CASE(modifier_without_underscore)
{
char const* text = R"(
contract test {
modifier m() {}
}
)";
BOOST_CHECK(expectError(text, true) == Error::Type::SyntaxError);
}

BOOST_AUTO_TEST_SUITE_END()

}
Expand Down