Skip to content

Commit

Permalink
Stricter check for member access to "this" in constructor.
Browse files Browse the repository at this point in the history
  • Loading branch information
ekpyron committed Apr 12, 2018
1 parent c3dc67d commit bf12e8e
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 5 deletions.
16 changes: 11 additions & 5 deletions libsolidity/analysis/StaticAnalyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ bool StaticAnalyzer::visit(Identifier const& _identifier)
if (var->isLocalVariable())
m_localVarUseCount[make_pair(var->id(), var)] += 1;
}

if (m_constructor && m_memberAccess && _identifier.name() == "this")
m_errorReporter.warning(_identifier.location(), "\"this\" used in constructor.");

return true;
}

Expand Down Expand Up @@ -152,6 +156,8 @@ bool StaticAnalyzer::visit(MemberAccess const& _memberAccess)
{
bool const v050 = m_currentContract->sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050);

m_memberAccess = true;

if (MagicType const* type = dynamic_cast<MagicType const*>(_memberAccess.expression().annotation().type.get()))
{
if (type->kind() == MagicType::Kind::Message && _memberAccess.memberName() == "gas")
Expand Down Expand Up @@ -206,14 +212,14 @@ bool StaticAnalyzer::visit(MemberAccess const& _memberAccess)
);
}

if (m_constructor && m_currentContract)
if (ContractType const* type = dynamic_cast<ContractType const*>(_memberAccess.expression().annotation().type.get()))
if (type->contractDefinition() == *m_currentContract)
m_errorReporter.warning(_memberAccess.location(), "\"this\" used in constructor.");

return true;
}

void StaticAnalyzer::endVisit(MemberAccess const&)
{
m_memberAccess = false;
}

bool StaticAnalyzer::visit(InlineAssembly const& _inlineAssembly)
{
if (!m_currentFunction)
Expand Down
4 changes: 4 additions & 0 deletions libsolidity/analysis/StaticAnalyzer.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ class StaticAnalyzer: private ASTConstVisitor
virtual bool visit(Identifier const& _identifier) override;
virtual bool visit(Return const& _return) override;
virtual bool visit(MemberAccess const& _memberAccess) override;
virtual void endVisit(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;
Expand All @@ -88,6 +89,9 @@ class StaticAnalyzer: private ASTConstVisitor
/// Flag that indicates a constructor.
bool m_constructor = false;

/// Flag that indicates a member access.
bool m_memberAccess = false;

/// Current contract.
ContractDefinition const* m_currentContract = nullptr;
};
Expand Down
13 changes: 13 additions & 0 deletions test/libsolidity/syntaxTests/constructor_this.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
contract C {
function f() public pure {}
constructor() public {
C c = this;
c.f();
this.f();
(this).f();
}
}
// ----
// Warning: c.f() should cause a warning as well.
// Warning: (80-84): "this" used in constructor.
// Warning: (99-103): "this" used in constructor.
8 changes: 8 additions & 0 deletions test/libsolidity/syntaxTests/parsing/constructor_self_ref.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
contract Foo {
bool public bar;

constructor(Foo other) public {
require(other.bar());
}
}
// ----
19 changes: 19 additions & 0 deletions test/libsolidity/syntaxTests/parsing/constructor_super.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
contract A {
function x() pure internal {}
}

contract B is A {
constructor() public {
super.x();
}

function x() pure internal {
require(false);
}
}

contract C is A {
constructor() public {
x();
}
}

0 comments on commit bf12e8e

Please sign in to comment.