From af64f1de61b2a02a01e741b9388c05de56ef839c Mon Sep 17 00:00:00 2001 From: Bhargava Shastry Date: Mon, 13 Apr 2020 23:16:31 +0200 Subject: [PATCH] Debug info and some fixes --- test/tools/ossfuzz/SolProtoAdaptor.cpp | 136 +++++++++++++++++++++---- test/tools/ossfuzz/SolProtoAdaptor.h | 4 +- test/tools/ossfuzz/protoToSol.cpp | 11 +- 3 files changed, 127 insertions(+), 24 deletions(-) diff --git a/test/tools/ossfuzz/SolProtoAdaptor.cpp b/test/tools/ossfuzz/SolProtoAdaptor.cpp index 573752e4a..44f0a7007 100644 --- a/test/tools/ossfuzz/SolProtoAdaptor.cpp +++ b/test/tools/ossfuzz/SolProtoAdaptor.cpp @@ -327,19 +327,18 @@ string SolBaseContract::name() SolBaseContract::SolBaseContract( ProtoBaseContract _base, string _name, - unsigned _startFunctionIndex, shared_ptr _prng ) { if (holds_alternative(_base)) m_base = make_shared( - SolContract(*get(_base), _name, _startFunctionIndex, _prng) + SolContract(*get(_base), _name, _prng) ); else { solAssert(holds_alternative(_base), "Sol proto adaptor: Invalid base contract"); m_base = make_shared( - SolInterface(*get(_base), _name, _startFunctionIndex, _prng) + SolInterface(*get(_base), _name, _prng) ); } } @@ -370,8 +369,8 @@ void SolInterface::overrideHelper( "Input specifies multiple function overrides with identical names" " and parameter types but different mutability." ); -#if 0 - cout << "Overriding function " << +#if 1 + cout << "Overriding interface function " << _function->name() << " explicitly inherited from " << _base->name() << @@ -404,9 +403,9 @@ void SolInterface::overrideHelper( // or not. Implicit override means that the overridden function is not // redeclared with the override keyword. bool explicitOverride = coinToss(); -#if 0 +#if 1 if (explicitOverride) - cout << "Overriding function " << + cout << "Overriding interface function " << _function->name() << " explicitly inherited from " << _base->name() << @@ -467,7 +466,7 @@ void SolInterface::addBases(Interface const& _interface) { for (auto &b: _interface.bases()) { - auto base = make_shared(SolInterface(b, newBaseName(), m_functionIndex, m_prng)); + auto base = make_shared(SolInterface(b, newBaseName(), m_prng)); m_baseInterfaces.push_back(base); // Worst case, we override all base functions so we // increment derived contract's function index by @@ -493,14 +492,12 @@ void SolInterface::addFunctions(Interface const& _interface) SolInterface::SolInterface( Interface const& _interface, string _name, - unsigned _startFunctionIndex, shared_ptr _prng ) { m_prng = _prng; m_interfaceName = _name; m_lastBaseName = m_interfaceName; - m_functionIndex = _startFunctionIndex; addBases(_interface); addOverrides(); addFunctions(_interface); @@ -591,6 +588,60 @@ interface is { .render(); } +void SolContract::disallowedBase(shared_ptr _base1, shared_ptr _base2) +{ + auto base1Type = _base1->type(); + auto base2Type = _base2->type(); + if (base1Type == SolBaseContract::BaseType::INTERFACE && base2Type == SolBaseContract::BaseType::INTERFACE) + { + for (auto &bf: _base1->interface()->m_interfaceFunctions) + for (auto &lbf: _base2->interface()->m_interfaceFunctions) + assertThrow( + bf != lbf, + langutil::FuzzerError, + "Sol proto adaptor: New base defines namesake function with different " + "visibility and/or state mutability" + ); + } + else if (base1Type == SolBaseContract::BaseType::INTERFACE && base2Type == SolBaseContract::BaseType::CONTRACT) + { + for (auto &bf: _base1->interface()->m_interfaceFunctions) + for (auto &lbf: _base2->contract()->m_contractFunctions) + if (bf->name() == lbf->name() && + ((bf->mutability() != lbf->mutability()) || (lbf->visibility() != SolFunctionVisibility::EXTERNAL))) + assertThrow( + false, + langutil::FuzzerError, + "Sol proto adaptor: New base defines namesake function with different " + "visibility and/or state mutability" + ); + } + else if (base1Type == SolBaseContract::BaseType::CONTRACT && base2Type == SolBaseContract::BaseType::INTERFACE) + { + for (auto &bf: _base1->contract()->m_contractFunctions) + for (auto &lbf: _base2->interface()->m_interfaceFunctions) + if (bf->name() == lbf->name() && + ((bf->mutability() != lbf->mutability()) || (bf->visibility() != SolFunctionVisibility::EXTERNAL))) + assertThrow( + false, + langutil::FuzzerError, + "Sol proto adaptor: New base defines namesake function with different " + "visibility and/or state mutability" + ); + } + else + { + for (auto &bf: _base1->contract()->m_contractFunctions) + for (auto &lbf: _base2->contract()->m_contractFunctions) + assertThrow( + bf != lbf, + langutil::FuzzerError, + "Sol proto adaptor: New base defines namesake function with different " + "visibility and/or state mutability" + ); + } +} + string SolContract::baseNames() const { ostringstream bases; @@ -714,6 +765,15 @@ void SolContract::interfaceFunctionOverride( ) ); multipleOverride = true; +#if 1 + std::cout << "Explicitly overriding interface " << + _function->name() << + " of " << + _base->name() << + " from " << + name() << + std::endl; +#endif break; } } @@ -729,6 +789,7 @@ void SolContract::interfaceFunctionOverride( if (abstract() && explicitOverride && !implement) virtualize = true; if (!multipleOverride) + { m_overriddenInterfaceFunctions.insert( pair( _function, @@ -747,6 +808,17 @@ void SolContract::interfaceFunctionOverride( } ) ); +#if 1 + std::cout << (explicitOverride ? "Explicitly" : "Implicitly") << + " overriding interface " << + _function->name() << + " of " << + _base->name() << + " from " << + name() << + std::endl; +#endif + } } void SolContract::contractFunctionOverride( @@ -802,6 +874,15 @@ void SolContract::contractFunctionOverride( ) ) ); +#if 1 + std::cout << "Explicitly overriding contract " << + _function->name() << + " of " << + _base->name() << + " from " << + name() << + std::endl; +#endif multipleOverride = true; break; } @@ -819,6 +900,7 @@ void SolContract::contractFunctionOverride( explicitOverride = coinToss(); if (!multipleOverride) + { m_overriddenContractFunctions.insert( pair( _function, @@ -837,6 +919,17 @@ void SolContract::contractFunctionOverride( } ) ); +#if 1 + std::cout << (explicitOverride ? "Explicitly" : "Implicitly") << + " overriding contract " << + _function->name() << + " of " << + _base->name() << + " from " << + name() << + std::endl; +#endif + } } void SolContract::addOverrides() @@ -893,9 +986,12 @@ void SolContract::addOverrides() // - They have been explicitly overridden and virtualized but unimplemented for (auto &m: base->contract()->m_overriddenInterfaceFunctions) { - solAssert(m.second.size() == 1, "Sol proto fuzzer: Cannot have left multiple override interface function unoverridden"); - if (!m.second[0]->explicitlyInherited() || (m.second[0]->virtualized() && !m.second[0]->implemented())) - interfaceFunctionOverride(m.second[0]->m_baseInterface, m.first); + std::cout << "Overriding " << m.first->name() << " from " << name() << std::endl; + if (m.second.size() == 1) + { + if (!m.second[0]->explicitlyInherited() || (m.second[0]->virtualized() && !m.second[0]->implemented())) + interfaceFunctionOverride(m.second[0]->m_baseInterface, m.first); + } } } } @@ -962,17 +1058,22 @@ void SolContract::addBases(Contract const& _contract) { case ContractOrInterface::kC: base = make_shared( - SolBaseContract(&b.c(), newBaseName(), m_functionIndex, m_prng) + SolBaseContract(&b.c(), newBaseName(), m_prng) ); break; case ContractOrInterface::kI: base = make_shared( - SolBaseContract(&b.i(), newBaseName(), m_functionIndex, m_prng) + SolBaseContract(&b.i(), newBaseName(), m_prng) ); break; case ContractOrInterface::CONTRACT_OR_INTERFACE_ONEOF_NOT_SET: continue; } + // Check for namesake functions with different visibility and/or + // state mutability. Bail out by throwing exception + if (m_baseContracts.size() > 1) + for (auto &existingBase: m_baseContracts) + disallowedBase(base, existingBase); m_baseContracts.push_back(base); // Worst case, we override all base functions so we // increment derived contract's function index by @@ -1076,7 +1177,10 @@ string SolContract::interfaceOverrideStr() { solAssert(f.second.size() == 1, "Inconsistent override map"); if (!f.second[0]->explicitlyInherited()) + { continue; + } + } string functionName = f.first->name(); overriddenFunctions << Whiskers(R"( @@ -1129,14 +1233,12 @@ string SolContract::str() SolContract::SolContract( Contract const& _contract, std::string _name, - unsigned _startFunctionIndex, shared_ptr _prng ) { m_prng = _prng; m_contractName = _name; m_lastBaseName = m_contractName; - m_functionIndex = _startFunctionIndex; m_abstract = _contract.abstract(); addBases(_contract); addOverrides(); diff --git a/test/tools/ossfuzz/SolProtoAdaptor.h b/test/tools/ossfuzz/SolProtoAdaptor.h index c4e647b79..87340be8e 100644 --- a/test/tools/ossfuzz/SolProtoAdaptor.h +++ b/test/tools/ossfuzz/SolProtoAdaptor.h @@ -251,7 +251,6 @@ struct SolBaseContract SolBaseContract( ProtoBaseContract _base, std::string _name, - unsigned _startFunctionIndex, std::shared_ptr _prng ); @@ -281,13 +280,13 @@ struct SolContract SolContract( Contract const& _contract, std::string _name, - unsigned _startFunctionIndex, std::shared_ptr _prng ); std::string str(); std::string interfaceOverrideStr(); std::string contractOverrideStr(); + void disallowedBase(std::shared_ptr _base1, std::shared_ptr _base2); void addFunctions(Contract const& _contract); void addBases(Contract const& _contract); void addOverrides(); @@ -364,7 +363,6 @@ struct SolInterface SolInterface( Interface const& _interface, std::string _interfaceName, - unsigned _startFunctionIndex, std::shared_ptr _prng ); diff --git a/test/tools/ossfuzz/protoToSol.cpp b/test/tools/ossfuzz/protoToSol.cpp index cb721f2dc..594ebd393 100644 --- a/test/tools/ossfuzz/protoToSol.cpp +++ b/test/tools/ossfuzz/protoToSol.cpp @@ -158,7 +158,7 @@ string ProtoConverter::visit(Contract const& _contract) openProgramScope(&_contract); try { - auto contract = SolContract(_contract, programName(&_contract), 0, m_randomGen); + auto contract = SolContract(_contract, programName(&_contract), m_randomGen); if (contract.validTest()) { m_contractTests.push_back(contract.pseudoRandomTest()); @@ -167,11 +167,14 @@ string ProtoConverter::visit(Contract const& _contract) // There is no point in generating a contract that can not provide // a valid test case, so we simply bail. else + { + std::cout << contract.str() << std::endl; return ""; + } } catch (langutil::FuzzerError const& error) { - cout << error.what() << endl; + std::cout << error.what() << std::endl; // Return empty string if input specification is invalid. return ""; } @@ -184,12 +187,12 @@ string ProtoConverter::visit(Interface const& _interface) openProgramScope(&_interface); try { - auto interface = SolInterface(_interface, programName(&_interface), 0, m_randomGen); + auto interface = SolInterface(_interface, programName(&_interface), m_randomGen); return interface.str(); } catch (langutil::FuzzerError const& error) { - cout << error.what() << endl; + std::cout << error.what() << std::endl; // Return empty string if input specification is invalid. return ""; }