From 68b7f401845ffdf838db7672823e2645af43b9a6 Mon Sep 17 00:00:00 2001 From: Bhargava Shastry Date: Wed, 17 Apr 2019 11:41:28 +0200 Subject: [PATCH] ossfuzz: Fixes buggy generation of duplicate case literals --- test/tools/ossfuzz/protoToYul.cpp | 55 ++++++++++++++++++++++++++++--- test/tools/ossfuzz/protoToYul.h | 5 +++ 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/test/tools/ossfuzz/protoToYul.cpp b/test/tools/ossfuzz/protoToYul.cpp index a998e3255..5e99d024d 100644 --- a/test/tools/ossfuzz/protoToYul.cpp +++ b/test/tools/ossfuzz/protoToYul.cpp @@ -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 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 "; diff --git a/test/tools/ossfuzz/protoToYul.h b/test/tools/ossfuzz/protoToYul.h index b38bcda91..6c78dbcaa 100644 --- a/test/tools/ossfuzz/protoToYul.h +++ b/test/tools/ossfuzz/protoToYul.h @@ -21,8 +21,11 @@ #include #include #include +#include #include +#include +#include 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 m_numVarsPerScope; int32_t m_numLiveVars; int32_t m_numNestedForLoops; std::stack m_inForScope; + std::stack> m_switchLiteralSetPerScope; }; } }