Merge pull request #6437 from ethereum/add-scoped-vars

Reference only those variables that are in scope.
This commit is contained in:
chriseth 2019-04-04 13:35:57 +02:00 committed by GitHub
commit afa24e1bf4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 35 additions and 12 deletions

View File

@ -69,10 +69,10 @@ void ProtoConverter::visit(Literal const& _x)
}
}
// We only reference x_0...x_9 that are I/O params of hardcoded function "foo"
// Reference any index in [0, m_numLiveVars-1] or [0, m_numLiveVars)
void ProtoConverter::visit(VarRef const& _x)
{
m_output << "x_" << (static_cast<uint32_t>(_x.varnum()) % 10);
m_output << "x_" << (static_cast<uint32_t>(_x.varnum()) % m_numLiveVars);
}
void ProtoConverter::visit(Expression const& _x)
@ -175,17 +175,19 @@ void ProtoConverter::visit(BinaryOp const& _x)
m_output << ")";
}
// New var numbering starts from x_10 until x_16
// New var numbering starts from x_10
void ProtoConverter::visit(VarDecl const& _x)
{
m_output << "let x_" << ((_x.id() % 7) + 10) << " := ";
m_output << "let x_" << m_numLiveVars << " := ";
visit(_x.expr());
m_numVarsPerScope.top()++;
m_numLiveVars++;
m_output << "\n";
}
void ProtoConverter::visit(TypedVarDecl const& _x)
{
m_output << "let x_" << ((_x.id() % 7) + 10);
m_output << "let x_" << m_numLiveVars;
switch (_x.type())
{
case TypedVarDecl::BOOL:
@ -244,6 +246,8 @@ void ProtoConverter::visit(TypedVarDecl const& _x)
m_output << " : u256\n";
break;
}
m_numVarsPerScope.top()++;
m_numLiveVars++;
}
void ProtoConverter::visit(UnaryOp const& _x)
@ -303,8 +307,12 @@ void ProtoConverter::visit(StoreFunc const& _x)
void ProtoConverter::visit(ForStmt const& _x)
{
m_output << "for { let i := 0 } lt(i, 0x100) { i := add(i, 0x20) } ";
std::string loopVarName("i_" + std::to_string(m_numNestedForLoops++));
m_output << "for { let " << loopVarName << " := 0 } "
<< "lt(" << loopVarName << ", 0x60) "
<< "{ " << loopVarName << " := add(" << loopVarName << ", 0x20) } ";
visit(_x.for_body());
--m_numNestedForLoops;
}
void ProtoConverter::visit(CaseStmt const& _x)
@ -366,10 +374,13 @@ void ProtoConverter::visit(Block const& _x)
{
if (_x.statements_size() > 0)
{
m_numVarsPerScope.push(0);
m_output << "{\n";
for (auto const& st: _x.statements())
visit(st);
m_output << "}\n";
m_numLiveVars -= m_numVarsPerScope.top();
m_numVarsPerScope.pop();
}
else
m_output << "{}\n";
@ -399,4 +410,4 @@ string ProtoConverter::protoToYul(const uint8_t* _data, size_t _size)
if (!message.ParsePartialFromArray(_data, _size))
return "#error invalid proto\n";
return functionToString(message);
}
}

View File

@ -20,6 +20,7 @@
#include <string>
#include <ostream>
#include <sstream>
#include <stack>
#include <test/tools/ossfuzz/yulProto.pb.h>
@ -32,6 +33,15 @@ namespace yul_fuzzer
class ProtoConverter
{
public:
ProtoConverter()
{
// The hard-coded function template foo has 10 parameters that are already "live"
m_numLiveVars = 10;
m_numVarsPerScope.push(m_numLiveVars);
m_numNestedForLoops = 0;
}
ProtoConverter(ProtoConverter const&) = delete;
ProtoConverter(ProtoConverter&&) = delete;
std::string functionToString(Function const& _input);
std::string protoToYul(uint8_t const* _data, size_t _size);
@ -59,7 +69,10 @@ private:
std::string createAlphaNum(std::string const& _strBytes) const;
std::ostringstream m_output;
std::stack<uint8_t> m_numVarsPerScope;
int32_t m_numLiveVars;
int32_t m_numNestedForLoops;
};
}
}
}
}

View File

@ -18,8 +18,7 @@
syntax = "proto2";
message VarDecl {
required int32 id = 1;
required Expression expr = 2;
required Expression expr = 1;
}
message TypedVarDecl {

View File

@ -63,4 +63,4 @@ DEFINE_PROTO_FUZZER(Function const& _input)
// Optimize
stack.optimize();
}
}

View File

@ -96,4 +96,4 @@ DEFINE_PROTO_FUZZER(Function const& _input)
bool isTraceEq = (os1.str() == os2.str());
yulAssert(isTraceEq, "Interpreted traces for optimized and unoptimized code differ.");
return;
}
}