Merge pull request #6539 from ethereum/fix-dup-case-literals

ossfuzz: Fixes buggy generation of duplicate case literals
This commit is contained in:
Leonardo 2019-04-19 00:40:26 +02:00 committed by GitHub
commit f8b1326712
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 55 additions and 5 deletions

View File

@ -31,7 +31,7 @@ string ProtoConverter::createHex(string const& _hexBytes) const
}); });
tmp = tmp.substr(0, 64); tmp = tmp.substr(0, 64);
} }
// We need this awkward if case hex literals cannot be empty. // We need this awkward if case because hex literals cannot be empty.
if (tmp.empty()) if (tmp.empty())
tmp = "1"; tmp = "1";
return tmp; return tmp;
@ -50,6 +50,41 @@ string ProtoConverter::createAlphaNum(string const& _strBytes) const
return tmp; return tmp;
} }
bool ProtoConverter::isCaseLiteralUnique(Literal const& _x)
{
std::string tmp;
bool isUnique = false;
bool isEmptyString = false;
switch (_x.literal_oneof_case())
{
case Literal::kIntval:
tmp = std::to_string(_x.intval());
break;
case Literal::kHexval:
tmp = "0x" + createHex(_x.hexval());
break;
case Literal::kStrval:
tmp = createAlphaNum(_x.strval());
if (tmp.empty())
{
isEmptyString = true;
tmp = std::to_string(0);
}
else
tmp = "\"" + tmp + "\"";
break;
case Literal::LITERAL_ONEOF_NOT_SET:
tmp = std::to_string(1);
break;
}
if (!_x.has_strval() || isEmptyString)
isUnique = m_switchLiteralSetPerScope.top().insert(dev::u256(tmp)).second;
else
isUnique = m_switchLiteralSetPerScope.top().insert(
dev::u256(dev::h256(tmp, dev::h256::FromBinary, dev::h256::AlignLeft))).second;
return isUnique;
}
void ProtoConverter::visit(Literal const& _x) void ProtoConverter::visit(Literal const& _x)
{ {
switch (_x.literal_oneof_case()) switch (_x.literal_oneof_case())
@ -319,21 +354,31 @@ void ProtoConverter::visit(ForStmt const& _x)
void ProtoConverter::visit(CaseStmt const& _x) void ProtoConverter::visit(CaseStmt const& _x)
{ {
m_output << "case "; // Silently ignore duplicate case literals
visit(_x.case_lit()); if (isCaseLiteralUnique(_x.case_lit()))
m_output << " "; {
visit(_x.case_block()); m_output << "case ";
visit(_x.case_lit());
m_output << " ";
visit(_x.case_block());
}
} }
void ProtoConverter::visit(SwitchStmt const& _x) void ProtoConverter::visit(SwitchStmt const& _x)
{ {
if (_x.case_stmt_size() > 0 || _x.has_default_block()) if (_x.case_stmt_size() > 0 || _x.has_default_block())
{ {
std::set<dev::u256> s;
m_switchLiteralSetPerScope.push(s);
m_output << "switch "; m_output << "switch ";
visit(_x.switch_expr()); visit(_x.switch_expr());
m_output << "\n"; m_output << "\n";
for (auto const& caseStmt: _x.case_stmt()) for (auto const& caseStmt: _x.case_stmt())
visit(caseStmt); visit(caseStmt);
m_switchLiteralSetPerScope.pop();
if (_x.has_default_block()) if (_x.has_default_block())
{ {
m_output << "default "; m_output << "default ";

View File

@ -21,8 +21,11 @@
#include <ostream> #include <ostream>
#include <sstream> #include <sstream>
#include <stack> #include <stack>
#include <set>
#include <test/tools/ossfuzz/yulProto.pb.h> #include <test/tools/ossfuzz/yulProto.pb.h>
#include <libdevcore/Common.h>
#include <libdevcore/FixedHash.h>
namespace yul namespace yul
{ {
@ -68,12 +71,14 @@ private:
std::string createHex(std::string const& _hexBytes) const; std::string createHex(std::string const& _hexBytes) const;
std::string createAlphaNum(std::string const& _strBytes) const; std::string createAlphaNum(std::string const& _strBytes) const;
bool isCaseLiteralUnique(Literal const&);
std::ostringstream m_output; std::ostringstream m_output;
std::stack<uint8_t> m_numVarsPerScope; std::stack<uint8_t> m_numVarsPerScope;
int32_t m_numLiveVars; int32_t m_numLiveVars;
int32_t m_numNestedForLoops; int32_t m_numNestedForLoops;
std::stack<bool> m_inForScope; std::stack<bool> m_inForScope;
std::stack<std::set<dev::u256>> m_switchLiteralSetPerScope;
}; };
} }
} }