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);
}
// 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())
tmp = "1";
return tmp;
@ -50,6 +50,41 @@ string ProtoConverter::createAlphaNum(string const& _strBytes) const
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)
{
switch (_x.literal_oneof_case())
@ -319,21 +354,31 @@ void ProtoConverter::visit(ForStmt const& _x)
void ProtoConverter::visit(CaseStmt const& _x)
{
m_output << "case ";
visit(_x.case_lit());
m_output << " ";
visit(_x.case_block());
// Silently ignore duplicate case literals
if (isCaseLiteralUnique(_x.case_lit()))
{
m_output << "case ";
visit(_x.case_lit());
m_output << " ";
visit(_x.case_block());
}
}
void ProtoConverter::visit(SwitchStmt const& _x)
{
if (_x.case_stmt_size() > 0 || _x.has_default_block())
{
std::set<dev::u256> s;
m_switchLiteralSetPerScope.push(s);
m_output << "switch ";
visit(_x.switch_expr());
m_output << "\n";
for (auto const& caseStmt: _x.case_stmt())
visit(caseStmt);
m_switchLiteralSetPerScope.pop();
if (_x.has_default_block())
{
m_output << "default ";

View File

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