mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Proto yul converter: Provide a flag to filter stateful instructions.
This commit is contained in:
parent
be5647735e
commit
a34308e4cb
@ -249,10 +249,19 @@ void ProtoConverter::visit(Expression const& _x)
|
|||||||
visit(_x.lowcall());
|
visit(_x.lowcall());
|
||||||
break;
|
break;
|
||||||
case Expression::kCreate:
|
case Expression::kCreate:
|
||||||
visit(_x.create());
|
// Create and create2 return address of created contract which
|
||||||
|
// may lead to state change via sstore of the returned address.
|
||||||
|
if (!m_filterStatefulInstructions)
|
||||||
|
visit(_x.create());
|
||||||
|
else
|
||||||
|
m_output << dictionaryToken();
|
||||||
break;
|
break;
|
||||||
case Expression::kUnopdata:
|
case Expression::kUnopdata:
|
||||||
if (m_isObject)
|
// Filter datasize and dataoffset because these instructions may return
|
||||||
|
// a value that is a function of optimisation. Therefore, when run on
|
||||||
|
// an EVM client, the execution traces for unoptimised vs optimised
|
||||||
|
// programs may differ. This ends up as a false-positive bug report.
|
||||||
|
if (m_isObject && !m_filterStatefulInstructions)
|
||||||
visit(_x.unopdata());
|
visit(_x.unopdata());
|
||||||
else
|
else
|
||||||
m_output << dictionaryToken();
|
m_output << dictionaryToken();
|
||||||
@ -572,6 +581,22 @@ void ProtoConverter::visit(UnaryOp const& _x)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The following instructions may lead to change of EVM state and are hence
|
||||||
|
// excluded to avoid false positives.
|
||||||
|
if (
|
||||||
|
m_filterStatefulInstructions &&
|
||||||
|
(
|
||||||
|
op == UnaryOp::EXTCODEHASH ||
|
||||||
|
op == UnaryOp::EXTCODESIZE ||
|
||||||
|
op == UnaryOp::BALANCE ||
|
||||||
|
op == UnaryOp::BLOCKHASH
|
||||||
|
)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
m_output << dictionaryToken();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (op)
|
switch (op)
|
||||||
{
|
{
|
||||||
case UnaryOp::NOT:
|
case UnaryOp::NOT:
|
||||||
@ -629,7 +654,26 @@ void ProtoConverter::visit(TernaryOp const& _x)
|
|||||||
|
|
||||||
void ProtoConverter::visit(NullaryOp const& _x)
|
void ProtoConverter::visit(NullaryOp const& _x)
|
||||||
{
|
{
|
||||||
switch (_x.op())
|
auto op = _x.op();
|
||||||
|
// The following instructions may lead to a change in EVM state and are
|
||||||
|
// excluded to avoid false positive reports.
|
||||||
|
if (
|
||||||
|
m_filterStatefulInstructions &&
|
||||||
|
(
|
||||||
|
op == NullaryOp::GAS ||
|
||||||
|
op == NullaryOp::CODESIZE ||
|
||||||
|
op == NullaryOp::ADDRESS ||
|
||||||
|
op == NullaryOp::TIMESTAMP ||
|
||||||
|
op == NullaryOp::NUMBER ||
|
||||||
|
op == NullaryOp::DIFFICULTY
|
||||||
|
)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
m_output << dictionaryToken();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (op)
|
||||||
{
|
{
|
||||||
case NullaryOp::MSIZE:
|
case NullaryOp::MSIZE:
|
||||||
m_output << "msize()";
|
m_output << "msize()";
|
||||||
@ -714,6 +758,11 @@ void ProtoConverter::visit(CopyFunc const& _x)
|
|||||||
if (type == CopyFunc::RETURNDATA && !m_evmVersion.supportsReturndata())
|
if (type == CopyFunc::RETURNDATA && !m_evmVersion.supportsReturndata())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Code copy may change state if e.g., some byte of code
|
||||||
|
// is stored to storage via a sequence of mload and sstore.
|
||||||
|
if (m_filterStatefulInstructions && type == CopyFunc::CODE)
|
||||||
|
return;
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case CopyFunc::CALLDATA:
|
case CopyFunc::CALLDATA:
|
||||||
@ -1380,7 +1429,7 @@ void ProtoConverter::visit(Statement const& _x)
|
|||||||
visit(_x.blockstmt());
|
visit(_x.blockstmt());
|
||||||
break;
|
break;
|
||||||
case Statement::kForstmt:
|
case Statement::kForstmt:
|
||||||
if (_x.forstmt().for_body().statements_size() > 0)
|
if (_x.forstmt().for_body().statements_size() > 0 && !m_filterUnboundedLoops)
|
||||||
visit(_x.forstmt());
|
visit(_x.forstmt());
|
||||||
break;
|
break;
|
||||||
case Statement::kBoundedforstmt:
|
case Statement::kBoundedforstmt:
|
||||||
@ -1405,7 +1454,10 @@ void ProtoConverter::visit(Statement const& _x)
|
|||||||
visit(_x.copy_func());
|
visit(_x.copy_func());
|
||||||
break;
|
break;
|
||||||
case Statement::kExtcodeCopy:
|
case Statement::kExtcodeCopy:
|
||||||
visit(_x.extcode_copy());
|
// Extcodecopy may change state if external code is copied via a
|
||||||
|
// sequence of mload/sstore.
|
||||||
|
if (!m_filterStatefulInstructions)
|
||||||
|
visit(_x.extcode_copy());
|
||||||
break;
|
break;
|
||||||
case Statement::kTerminatestmt:
|
case Statement::kTerminatestmt:
|
||||||
visit(_x.terminatestmt());
|
visit(_x.terminatestmt());
|
||||||
|
@ -39,7 +39,10 @@ namespace solidity::yul::test::yul_fuzzer
|
|||||||
class ProtoConverter
|
class ProtoConverter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ProtoConverter()
|
ProtoConverter(
|
||||||
|
bool _filterStatefulInstructions = false,
|
||||||
|
bool _filterUnboundedLoops = false
|
||||||
|
)
|
||||||
{
|
{
|
||||||
m_funcVars = std::vector<std::vector<std::vector<std::string>>>{};
|
m_funcVars = std::vector<std::vector<std::vector<std::string>>>{};
|
||||||
m_globalVars = std::vector<std::vector<std::string>>{};
|
m_globalVars = std::vector<std::vector<std::string>>{};
|
||||||
@ -54,6 +57,8 @@ public:
|
|||||||
m_objectId = 0;
|
m_objectId = 0;
|
||||||
m_isObject = false;
|
m_isObject = false;
|
||||||
m_forInitScopeExtEnabled = true;
|
m_forInitScopeExtEnabled = true;
|
||||||
|
m_filterStatefulInstructions = _filterStatefulInstructions;
|
||||||
|
m_filterUnboundedLoops = _filterUnboundedLoops;
|
||||||
}
|
}
|
||||||
ProtoConverter(ProtoConverter const&) = delete;
|
ProtoConverter(ProtoConverter const&) = delete;
|
||||||
ProtoConverter(ProtoConverter&&) = delete;
|
ProtoConverter(ProtoConverter&&) = delete;
|
||||||
@ -389,5 +394,11 @@ private:
|
|||||||
bool m_forInitScopeExtEnabled;
|
bool m_forInitScopeExtEnabled;
|
||||||
/// Object that holds the targeted evm version specified by protobuf input
|
/// Object that holds the targeted evm version specified by protobuf input
|
||||||
solidity::langutil::EVMVersion m_evmVersion;
|
solidity::langutil::EVMVersion m_evmVersion;
|
||||||
|
/// Flag that, if set, stops the converter from generating state changing
|
||||||
|
/// opcodes.
|
||||||
|
bool m_filterStatefulInstructions;
|
||||||
|
/// Flat that, if set, stops the converter from generating potentially
|
||||||
|
/// unbounded loops.
|
||||||
|
bool m_filterUnboundedLoops;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user