mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #5242 from ethereum/someChecks
Some well-formedness checks for the Yul AST.
This commit is contained in:
commit
f714b0dd7c
@ -110,3 +110,26 @@ string dev::getChecksummedAddress(string const& _addr)
|
|||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool dev::isValidHex(string const& _string)
|
||||||
|
{
|
||||||
|
if (_string.substr(0, 2) != "0x")
|
||||||
|
return false;
|
||||||
|
if (_string.find_first_not_of("0123456789abcdefABCDEF", 2) != string::npos)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dev::isValidDecimal(string const& _string)
|
||||||
|
{
|
||||||
|
if (_string.empty())
|
||||||
|
return false;
|
||||||
|
if (_string == "0")
|
||||||
|
return true;
|
||||||
|
// No leading zeros
|
||||||
|
if (_string.front() == '0')
|
||||||
|
return false;
|
||||||
|
if (_string.find_first_not_of("0123456789") != string::npos)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@ -272,4 +272,7 @@ bool passesAddressChecksum(std::string const& _str, bool _strict);
|
|||||||
/// @param hex strings that look like an address
|
/// @param hex strings that look like an address
|
||||||
std::string getChecksummedAddress(std::string const& _addr);
|
std::string getChecksummedAddress(std::string const& _addr);
|
||||||
|
|
||||||
|
bool isValidHex(std::string const& _string);
|
||||||
|
bool isValidDecimal(std::string const& _string);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,8 @@
|
|||||||
#include <libsolidity/inlineasm/AsmData.h>
|
#include <libsolidity/inlineasm/AsmData.h>
|
||||||
#include <libsolidity/interface/Exceptions.h>
|
#include <libsolidity/interface/Exceptions.h>
|
||||||
|
|
||||||
|
#include <libdevcore/CommonData.h>
|
||||||
|
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <boost/algorithm/string/replace.hpp>
|
#include <boost/algorithm/string/replace.hpp>
|
||||||
#include <boost/range/adaptor/transformed.hpp>
|
#include <boost/range/adaptor/transformed.hpp>
|
||||||
@ -41,6 +43,7 @@ using namespace dev::solidity::assembly;
|
|||||||
string AsmPrinter::operator()(assembly::Instruction const& _instruction)
|
string AsmPrinter::operator()(assembly::Instruction const& _instruction)
|
||||||
{
|
{
|
||||||
solAssert(!m_yul, "");
|
solAssert(!m_yul, "");
|
||||||
|
solAssert(isValidInstruction(_instruction.instruction), "Invalid instruction");
|
||||||
return boost::to_lower_copy(instructionInfo(_instruction.instruction).name);
|
return boost::to_lower_copy(instructionInfo(_instruction.instruction).name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,8 +52,10 @@ string AsmPrinter::operator()(assembly::Literal const& _literal)
|
|||||||
switch (_literal.kind)
|
switch (_literal.kind)
|
||||||
{
|
{
|
||||||
case LiteralKind::Number:
|
case LiteralKind::Number:
|
||||||
|
solAssert(isValidDecimal(_literal.value) || isValidHex(_literal.value), "Invalid number literal");
|
||||||
return _literal.value + appendTypeName(_literal.type);
|
return _literal.value + appendTypeName(_literal.type);
|
||||||
case LiteralKind::Boolean:
|
case LiteralKind::Boolean:
|
||||||
|
solAssert(_literal.value == "true" || _literal.value == "false", "Invalid bool literal.");
|
||||||
return ((_literal.value == "true") ? "true" : "false") + appendTypeName(_literal.type);
|
return ((_literal.value == "true") ? "true" : "false") + appendTypeName(_literal.type);
|
||||||
case LiteralKind::String:
|
case LiteralKind::String:
|
||||||
break;
|
break;
|
||||||
@ -87,12 +92,14 @@ string AsmPrinter::operator()(assembly::Literal const& _literal)
|
|||||||
|
|
||||||
string AsmPrinter::operator()(assembly::Identifier const& _identifier)
|
string AsmPrinter::operator()(assembly::Identifier const& _identifier)
|
||||||
{
|
{
|
||||||
|
solAssert(!_identifier.name.empty(), "Invalid identifier.");
|
||||||
return _identifier.name;
|
return _identifier.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
string AsmPrinter::operator()(assembly::FunctionalInstruction const& _functionalInstruction)
|
string AsmPrinter::operator()(assembly::FunctionalInstruction const& _functionalInstruction)
|
||||||
{
|
{
|
||||||
solAssert(!m_yul, "");
|
solAssert(!m_yul, "");
|
||||||
|
solAssert(isValidInstruction(_functionalInstruction.instruction), "Invalid instruction");
|
||||||
return
|
return
|
||||||
boost::to_lower_copy(instructionInfo(_functionalInstruction.instruction).name) +
|
boost::to_lower_copy(instructionInfo(_functionalInstruction.instruction).name) +
|
||||||
"(" +
|
"(" +
|
||||||
@ -110,12 +117,14 @@ string AsmPrinter::operator()(ExpressionStatement const& _statement)
|
|||||||
string AsmPrinter::operator()(assembly::Label const& _label)
|
string AsmPrinter::operator()(assembly::Label const& _label)
|
||||||
{
|
{
|
||||||
solAssert(!m_yul, "");
|
solAssert(!m_yul, "");
|
||||||
|
solAssert(!_label.name.empty(), "Invalid label.");
|
||||||
return _label.name + ":";
|
return _label.name + ":";
|
||||||
}
|
}
|
||||||
|
|
||||||
string AsmPrinter::operator()(assembly::StackAssignment const& _assignment)
|
string AsmPrinter::operator()(assembly::StackAssignment const& _assignment)
|
||||||
{
|
{
|
||||||
solAssert(!m_yul, "");
|
solAssert(!m_yul, "");
|
||||||
|
solAssert(!_assignment.variableName.name.empty(), "Invalid variable name.");
|
||||||
return "=: " + (*this)(_assignment.variableName);
|
return "=: " + (*this)(_assignment.variableName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +142,7 @@ string AsmPrinter::operator()(assembly::VariableDeclaration const& _variableDecl
|
|||||||
string out = "let ";
|
string out = "let ";
|
||||||
out += boost::algorithm::join(
|
out += boost::algorithm::join(
|
||||||
_variableDeclaration.variables | boost::adaptors::transformed(
|
_variableDeclaration.variables | boost::adaptors::transformed(
|
||||||
[this](TypedName variable) { return variable.name + appendTypeName(variable.type); }
|
[this](TypedName argument) { return formatTypedName(argument); }
|
||||||
),
|
),
|
||||||
", "
|
", "
|
||||||
);
|
);
|
||||||
@ -147,10 +156,11 @@ string AsmPrinter::operator()(assembly::VariableDeclaration const& _variableDecl
|
|||||||
|
|
||||||
string AsmPrinter::operator()(assembly::FunctionDefinition const& _functionDefinition)
|
string AsmPrinter::operator()(assembly::FunctionDefinition const& _functionDefinition)
|
||||||
{
|
{
|
||||||
|
solAssert(!_functionDefinition.name.empty(), "Invalid function name.");
|
||||||
string out = "function " + _functionDefinition.name + "(";
|
string out = "function " + _functionDefinition.name + "(";
|
||||||
out += boost::algorithm::join(
|
out += boost::algorithm::join(
|
||||||
_functionDefinition.parameters | boost::adaptors::transformed(
|
_functionDefinition.parameters | boost::adaptors::transformed(
|
||||||
[this](TypedName argument) { return argument.name + appendTypeName(argument.type); }
|
[this](TypedName argument) { return formatTypedName(argument); }
|
||||||
),
|
),
|
||||||
", "
|
", "
|
||||||
);
|
);
|
||||||
@ -160,7 +170,7 @@ string AsmPrinter::operator()(assembly::FunctionDefinition const& _functionDefin
|
|||||||
out += " -> ";
|
out += " -> ";
|
||||||
out += boost::algorithm::join(
|
out += boost::algorithm::join(
|
||||||
_functionDefinition.returnVariables | boost::adaptors::transformed(
|
_functionDefinition.returnVariables | boost::adaptors::transformed(
|
||||||
[this](TypedName argument) { return argument.name + appendTypeName(argument.type); }
|
[this](TypedName argument) { return formatTypedName(argument); }
|
||||||
),
|
),
|
||||||
", "
|
", "
|
||||||
);
|
);
|
||||||
@ -181,11 +191,13 @@ string AsmPrinter::operator()(assembly::FunctionCall const& _functionCall)
|
|||||||
|
|
||||||
string AsmPrinter::operator()(If const& _if)
|
string AsmPrinter::operator()(If const& _if)
|
||||||
{
|
{
|
||||||
|
solAssert(_if.condition, "Invalid if condition.");
|
||||||
return "if " + boost::apply_visitor(*this, *_if.condition) + "\n" + (*this)(_if.body);
|
return "if " + boost::apply_visitor(*this, *_if.condition) + "\n" + (*this)(_if.body);
|
||||||
}
|
}
|
||||||
|
|
||||||
string AsmPrinter::operator()(Switch const& _switch)
|
string AsmPrinter::operator()(Switch const& _switch)
|
||||||
{
|
{
|
||||||
|
solAssert(_switch.expression, "Invalid expression pointer.");
|
||||||
string out = "switch " + boost::apply_visitor(*this, *_switch.expression);
|
string out = "switch " + boost::apply_visitor(*this, *_switch.expression);
|
||||||
for (auto const& _case: _switch.cases)
|
for (auto const& _case: _switch.cases)
|
||||||
{
|
{
|
||||||
@ -200,6 +212,7 @@ string AsmPrinter::operator()(Switch const& _switch)
|
|||||||
|
|
||||||
string AsmPrinter::operator()(assembly::ForLoop const& _forLoop)
|
string AsmPrinter::operator()(assembly::ForLoop const& _forLoop)
|
||||||
{
|
{
|
||||||
|
solAssert(_forLoop.condition, "Invalid for loop condition.");
|
||||||
string out = "for ";
|
string out = "for ";
|
||||||
out += (*this)(_forLoop.pre);
|
out += (*this)(_forLoop.pre);
|
||||||
out += "\n";
|
out += "\n";
|
||||||
@ -223,6 +236,12 @@ string AsmPrinter::operator()(Block const& _block)
|
|||||||
return "{\n " + body + "\n}";
|
return "{\n " + body + "\n}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string AsmPrinter::formatTypedName(TypedName _variable) const
|
||||||
|
{
|
||||||
|
solAssert(!_variable.name.empty(), "Invalid variable name.");
|
||||||
|
return _variable.name + appendTypeName(_variable.type);
|
||||||
|
}
|
||||||
|
|
||||||
string AsmPrinter::appendTypeName(std::string const& _type) const
|
string AsmPrinter::appendTypeName(std::string const& _type) const
|
||||||
{
|
{
|
||||||
if (m_yul)
|
if (m_yul)
|
||||||
|
@ -55,6 +55,7 @@ public:
|
|||||||
std::string operator()(assembly::Block const& _block);
|
std::string operator()(assembly::Block const& _block);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
std::string formatTypedName(TypedName _variable) const;
|
||||||
std::string appendTypeName(std::string const& _type) const;
|
std::string appendTypeName(std::string const& _type) const;
|
||||||
|
|
||||||
bool m_yul = false;
|
bool m_yul = false;
|
||||||
|
@ -209,6 +209,7 @@ u256 Pattern::d() const
|
|||||||
{
|
{
|
||||||
Literal const& literal = boost::get<Literal>(matchGroupValue());
|
Literal const& literal = boost::get<Literal>(matchGroupValue());
|
||||||
assertThrow(literal.kind == assembly::LiteralKind::Number, OptimizerException, "");
|
assertThrow(literal.kind == assembly::LiteralKind::Number, OptimizerException, "");
|
||||||
|
assertThrow(isValidDecimal(literal.value) || isValidHex(literal.value), OptimizerException, "");
|
||||||
return u256(literal.value);
|
return u256(literal.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
contract C {
|
||||||
|
function f() public pure {
|
||||||
|
assembly {
|
||||||
|
function f(a, b) {}
|
||||||
|
f()
|
||||||
|
f(1,)
|
||||||
|
f(,1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// ParserError: (113-114): Literal, identifier or instruction expected.
|
||||||
|
// ParserError: (113-114): Expected primary expression.
|
@ -0,0 +1,10 @@
|
|||||||
|
contract C {
|
||||||
|
function f() public pure {
|
||||||
|
assembly {
|
||||||
|
function (a, b) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// ParserError: (72-73): Expected identifier but got '('
|
||||||
|
// ParserError: (79-80): Expected ';' but got '{'
|
@ -0,0 +1,10 @@
|
|||||||
|
contract C {
|
||||||
|
function f() public pure {
|
||||||
|
assembly {
|
||||||
|
let x := 0100
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// ParserError: (72-73): Literal, identifier or instruction expected.
|
||||||
|
// ParserError: (72-73): Expected primary expression.
|
@ -0,0 +1,11 @@
|
|||||||
|
contract C {
|
||||||
|
function f() public pure {
|
||||||
|
assembly {
|
||||||
|
let x := mload(0)
|
||||||
|
:= 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// ParserError: (87-88): Literal, identifier or instruction expected.
|
||||||
|
// ParserError: (87-88): Expected primary expression.
|
Loading…
Reference in New Issue
Block a user