From 05139500fb44c1ff574756b3a5d10d46674c236d Mon Sep 17 00:00:00 2001 From: Federico Bond Date: Thu, 1 Dec 2016 10:55:02 -0300 Subject: Warn about using msg.value in non-payable function --- libsolidity/analysis/StaticAnalyzer.cpp | 78 +++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 libsolidity/analysis/StaticAnalyzer.cpp (limited to 'libsolidity/analysis/StaticAnalyzer.cpp') diff --git a/libsolidity/analysis/StaticAnalyzer.cpp b/libsolidity/analysis/StaticAnalyzer.cpp new file mode 100644 index 00000000..c39f874e --- /dev/null +++ b/libsolidity/analysis/StaticAnalyzer.cpp @@ -0,0 +1,78 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ +/** + * @author Federico Bond + * @date 2016 + * Static analyzer and checker. + */ + +#include +#include +#include + +using namespace std; +using namespace dev; +using namespace dev::solidity; + + +bool StaticAnalyzer::analyze(SourceUnit const& _sourceUnit) +{ + _sourceUnit.accept(*this); + return Error::containsOnlyWarnings(m_errors); +} + +bool StaticAnalyzer::visit(ContractDefinition const& _contract) +{ + m_library = _contract.isLibrary(); + return true; +} + +void StaticAnalyzer::endVisit(ContractDefinition const&) +{ + m_library = false; +} + +bool StaticAnalyzer::visit(FunctionDefinition const& _function) +{ + m_nonPayablePublic = _function.isPublic() && !_function.isPayable(); + return true; +} + +void StaticAnalyzer::endVisit(FunctionDefinition const&) +{ + m_nonPayablePublic = false; +} + +bool StaticAnalyzer::visit(MemberAccess const& _memberAccess) +{ + if (m_nonPayablePublic && !m_library) + if (MagicType const* type = dynamic_cast(_memberAccess.expression().annotation().type.get())) + if (type->kind() == MagicType::Kind::Message && _memberAccess.memberName() == "value") + warning(_memberAccess.location(), "\"msg.value\" used in non-payable function. Do you want to add the \"payable\" modifier to this function?"); + + return true; +} + +void StaticAnalyzer::warning(SourceLocation const& _location, string const& _description) +{ + auto err = make_shared(Error::Type::Warning); + *err << + errinfo_sourceLocation(_location) << + errinfo_comment(_description); + + m_errors.push_back(err); +} -- cgit v1.2.3