diff --git a/test/tools/ossfuzz/SolProtoAdaptor.cpp b/test/tools/ossfuzz/SolProtoAdaptor.cpp index 3696d1601..31775bcde 100644 --- a/test/tools/ossfuzz/SolProtoAdaptor.cpp +++ b/test/tools/ossfuzz/SolProtoAdaptor.cpp @@ -21,8 +21,6 @@ #include -#include - #include using namespace solidity::test::solprotofuzzer::adaptor; @@ -173,6 +171,7 @@ SolContractFunction::SolContractFunction( ContractFunction const& _function, std::string _contractName, std::string _functionName, + bool _implemented, std::string _returnValue ) { @@ -182,6 +181,7 @@ SolContractFunction::SolContractFunction( m_mutability = mutabilityConverter(_function.mut()); m_virtual = _function.virtualfunc(); m_returnValue = _returnValue; + m_implemented = _implemented; } bool SolContractFunction::operator==(SolContractFunction const& _rhs) const @@ -198,8 +198,25 @@ bool SolContractFunction::operator!=(SolContractFunction const& _rhs) const return name() != _rhs.name(); } +bool SolContractFunction::disallowed() const +{ + // Private virtual functions are disallowed + if (visibility() == SolFunctionVisibility::PRIVATE && isVirtual()) + return true; + // Private payable functions are disallowed + else if (visibility() == SolFunctionVisibility::PRIVATE && mutability() == SolFunctionStateMutability::PAYABLE) + return true; + // Internal payable functions are disallowed + else if (visibility() == SolFunctionVisibility::INTERNAL && mutability() == SolFunctionStateMutability::PAYABLE) + return true; + return false; +} + string SolContractFunction::str() const { + if (disallowed()) + return ""; + string bodyStr = Whiskers(R"( { return ; @@ -208,16 +225,14 @@ string SolContractFunction::str() const .render(); return Whiskers(R"( - function () override - virtual + function () virtual returns (uint);)") ("functionName", name()) ("isVirtual", isVirtual()) - ("isOverride", "_override") ("visibility", functionVisibility(visibility())) ("stateMutability", functionMutability(mutability())) ("body", bodyStr) - ("isImplemented", "_implement") + ("isImplemented", implemented()) .render(); } @@ -253,16 +268,37 @@ string SolLibraryFunction::str() const .render(); } +SolBaseContract::BaseType SolBaseContract::type() const +{ + if (holds_alternative>(m_base)) + return BaseType::INTERFACE; + else + { + solAssert(holds_alternative>(m_base), "Sol proto fuzzer: Invalid base contract"); + return BaseType::CONTRACT; + } +} + +string SolBaseContract::str() +{ + switch (type()) + { + case BaseType::INTERFACE: + return interface()->str(); + case BaseType::CONTRACT: + return contract()->str(); + } +} + SolBaseContract::SolBaseContract(ProtoBaseContract _base, string _name, shared_ptr _prng) { - if (auto c = get(_base)) - m_base.push_back( - make_shared(SolContract(*c, _name, _prng)) - ); - else if (auto i = get(_base)) - m_base.push_back( - make_shared(SolInterface(*i, _name, _prng)) - ); + if (holds_alternative(_base)) + m_base = make_shared(SolContract(*get(_base), _name, _prng)); + else + { + solAssert(holds_alternative(_base), "Sol proto adaptor: Invalid base contract"); + m_base = make_shared(SolInterface(*get(_base), _name, _prng)); + } } void SolInterface::overrideHelper( @@ -314,7 +350,7 @@ void SolInterface::overrideHelper( // Use a pseudo-random coin flip to decide whether to override explicitly // or not. Implicit override means that the overridden function is not // redeclared with the override keyword. - bool explicitOverride = coinFlip(); + bool explicitOverride = coinToss(); // If function has not been overridden, add new override pseudo-randomly if (!multipleOverride) m_overrideMap.insert( @@ -478,37 +514,49 @@ interface is { bool SolContract::validTest() const { - return m_contractFunctionMap.size() > 0; + // Check if at least one contract has one valid test function + for (auto &c: m_contractFunctionMap) + if (c.second.size() > 1) + return true; + return false; } -tuple SolContract::pseudoRandomTest() +tuple SolContract::validContractTest() { - solAssert(m_contractFunctionMap.size() > 0, "Sol proto adaptor: Empty contract map"); string chosenContractName{}; string chosenFunctionName{}; string expectedOutput{}; - unsigned numFunctions = m_contractFunctionMap.size(); - unsigned contractIdx = randomNumber() % numFunctions; + unsigned numContracts = m_contractFunctionMap.size(); + unsigned contractIdx = random() % numContracts; unsigned functionIdx = 0; unsigned mapIdx = 0; for (auto &e: m_contractFunctionMap) { if (contractIdx == mapIdx) { - chosenContractName = e.first; - functionIdx = random() % e.second.size(); - unsigned functionMapIdx = 0; - for (auto &f: e.second) + // Recurse if chosen contract has no valid test cases + // We can be sure there is at least one contract with + // a valid test case because validTest() has been + // asserted by caller of this function. + if (e.second.size() == 0) + return validContractTest(); + else { - if (functionIdx == functionMapIdx) + chosenContractName = e.first; + functionIdx = random() % e.second.size(); + unsigned functionMapIdx = 0; + for (auto &f: e.second) { - chosenFunctionName = f.first; - expectedOutput = f.second; - break; + if (functionIdx == functionMapIdx) + { + chosenFunctionName = f.first; + expectedOutput = f.second; + break; + } + functionMapIdx++; } - functionMapIdx++; + break; } - break; } mapIdx++; } @@ -517,29 +565,261 @@ tuple SolContract::pseudoRandomTest() return tuple(chosenContractName, chosenFunctionName, expectedOutput); } -void SolContract::overrideHelper() +tuple SolContract::pseudoRandomTest() { + solAssert(validTest(), "Sol proto adaptor: No valid contract test cases"); + return validContractTest(); +} +void SolContract::interfaceFunctionOverride( + std::shared_ptr _base, + std::shared_ptr _function +) +{ + string functionName = _function->name(); + auto mutability = _function->mutability(); + + // Check if two or more bases define this function + bool multipleOverride = false; + // If function has already been overridden, add + // new base to list of overridden bases + for (auto &m: m_overriddenInterfaceFunctions) + { + // Must override if two or more bases define the + // same function + if (m.first->operator==(*_function)) + { + // Report error if state mutability of identically + // named functions differ + if (m.first->mutability() != mutability) + assertThrow( + false, + langutil::FuzzerError, + "Input specifies multiple function overrides with identical names" + " and parameter types but different mutability." + ); + // Should interface function be implemented: May be but if not it must be marked virtual + // Should it be explicitly overridden: Yes + // Should it be marked virtual: May be + bool implement = abstract() ? coinToss() : true; + bool virtualize = coinToss(); + if (abstract() && !implement) + virtualize = true; + // Add new base to list of overridden bases + m_overriddenInterfaceFunctions[m.first].push_back( + shared_ptr( + make_shared( + IFunctionOverride( + _base, + _function, + this, + implement, + virtualize, + true, + newReturnValue() + ) + ) + ) + ); + multipleOverride = true; + break; + } + } + // Use a pseudo-random coin toss to decide whether to override explicitly + // or not. Implicit override means that the overridden function is not + // redeclared with the override keyword. + bool explicitOverride = abstract() ? coinToss() : true; + // If function has not been overridden, add new override pseudo-randomly + // Should it be virtual: May be but only matters for explicit overrides + // Should it be implemented: If non abstract, otherwise may be + bool virtualize = explicitOverride ? coinToss() : false; + bool implement = abstract() ? coinToss() : true; + if (abstract() && explicitOverride && !implement) + virtualize = true; + if (!multipleOverride) + m_overriddenInterfaceFunctions.insert( + pair( + _function, + vector>{ + make_shared( + IFunctionOverride( + _base, + _function, + this, + implement, + virtualize, + explicitOverride, + newReturnValue() + ) + ) + } + ) + ); +} + +void SolContract::contractFunctionOverride( + std::shared_ptr _base, + std::shared_ptr _function +) +{ + string functionName = _function->name(); + auto mutability = _function->mutability(); + auto visibility = _function->visibility(); + + // Check if two or more bases define this function + bool multipleOverride = false; + // If function has already been overridden, add + // new base to list of overridden bases + for (auto &m: m_overriddenContractFunctions) + { + // Must override if two or more bases define the + // same function + if (m.first->operator==(*_function)) + { + // Report error if state mutability of identically + // named functions differ + if (m.first->mutability() != mutability || m.first->visibility() != visibility) + assertThrow( + false, + langutil::FuzzerError, + "Input specifies multiple contract function overrides with identical names" + " and parameter types but different mutability and/or visibility." + ); + /* Case 1: Base and derived are abstract + * Case 2: Base and derived not abstract + * Case 3: Derived abstract, base not + * Case 4: Derived non abstract, base abstract + */ + bool implement = abstract() ? coinToss() : true; + bool virtualize = coinToss(); + if (abstract() && !implement) + virtualize = true; + // Add new base to list of overridden bases + m_overriddenContractFunctions[m.first].push_back( + shared_ptr( + make_shared( + CFunctionOverride( + _base, + _function, + this, + implement, + virtualize, + true, + newReturnValue() + ) + ) + ) + ); + multipleOverride = true; + break; + } + } + bool implement; + if (_function->implemented()) + implement = true; + else + implement = abstract() ? coinToss() : true; + bool virtualize = coinToss(); + if (!implement && abstract()) + virtualize = true; + bool explicitOverride = true; + if (_base->abstract() && !implement && abstract()) + explicitOverride = coinToss(); + + if (!multipleOverride) + m_overriddenContractFunctions.insert( + pair( + _function, + vector>{ + make_shared( + CFunctionOverride( + _base, + _function, + this, + implement, + virtualize, + explicitOverride, + newReturnValue() + ) + ) + } + ) + ); } void SolContract::addOverrides() { - + for (auto &base: m_baseContracts) + { + // Check if base is contract or interface + if (base->type() == SolBaseContract::BaseType::INTERFACE) + { + // Override interface functions + for (auto &f: base->interface()->m_interfaceFunctions) + { + interfaceFunctionOverride(base->interface(), f); + } + // Override interface overrides + for (auto &m: base->interface()->m_overrideMap) + { + interfaceFunctionOverride(base->interface(), m.first); + } + } + else + { + solAssert(base->type() == SolBaseContract::BaseType::CONTRACT, "Sol proto fuzzer: Base contract neither interface nor contract"); + // Override contract functions + for (auto &f: base->contract()->m_contractFunctions) + { + contractFunctionOverride(base->contract(), f); + } + // Override contract overrides + for (auto &m: base->contract()->m_overriddenContractFunctions) + { + for (auto &f: m.second) + contractFunctionOverride(base->contract(), f->baseFunction()); + } + } + } } void SolContract::addFunctions(Contract const& _contract) { + bool abs = abstract(); + string contractName = name(); + // Add contract to contract function map only if the contract + // is not abstract. + if (!abs) + m_contractFunctionMap.insert(pair(contractName, map{})); + // Add functions for (auto &f: _contract.funcdef()) - m_contractFunctions.push_back( - make_unique( - SolContractFunction( - f, - m_contractName, - newFunctionName(), - newReturnValue() - ) + { + auto function = make_shared( + SolContractFunction( + f, + contractName, + newFunctionName(), + (abs ? coinToss() : true), + newReturnValue() ) ); + m_contractFunctions.push_back(function); + // If contract is not abstract, add its public and external + // functions to contract function map. + if (!abs) + { + auto visibility = function->visibility(); + string functionName = function->name(); + string expectedOutput = function->returnValue(); + // Register only public and external contract functions because only they can + // be called from a different contract. + if (visibility == SolFunctionVisibility::PUBLIC || visibility == SolFunctionVisibility::EXTERNAL) + { + solAssert(!m_contractFunctionMap[contractName].count(functionName), "Sol proto adaptor: Duplicate contract function"); + m_contractFunctionMap[contractName].insert(pair(functionName, expectedOutput)); + } + } + } } void SolContract::addBases(Contract const& _contract) @@ -550,14 +830,14 @@ void SolContract::addBases(Contract const& _contract) { case ContractOrInterface::kC: m_baseContracts.push_back( - make_unique( + make_shared( SolBaseContract(&b.c(), newBaseName(), m_prng) ) ); break; case ContractOrInterface::kI: m_baseContracts.push_back( - make_unique( + make_shared( SolBaseContract(&b.i(), newBaseName(), m_prng) ) ); @@ -568,9 +848,135 @@ void SolContract::addBases(Contract const& _contract) } } +string SolContract::contractOverrideStr() const +{ + ostringstream overriddenFunctions; + for (auto &f: m_overriddenContractFunctions) + { + string bodyStr = Whiskers(R"( + { + return ; + })") + ("uint", f.second[0]->returnValue()) + .render(); + + bool implemented = f.second[0]->implemented(); + bool virtualized = f.second[0]->virtualized(); + + ostringstream overriddenBaseNames; + if (f.second.size() > 1) + { + string sep{}; + for (auto &b: f.second) + { + overriddenBaseNames << Whiskers(R"()") + ("sep", sep) + ("name", b->baseName()) + .render(); + if (sep.empty()) + sep = ", "; + } + } + else + { + assertThrow( + f.second.size() == 1, + langutil::FuzzerError, + "Inconsistent override map" + ); + if (!f.second[0]->explicitlyInherited()) + continue; + } + overriddenFunctions << Whiskers(R"( + function () virtual + override() returns (uint);)") + ("functionName", f.first->name()) + ("visibility", functionVisibility(f.first->visibility())) + ("stateMutability", functionMutability(f.first->mutability())) + ("isVirtual", virtualized) + ("multiple", f.second.size() > 1) + ("baseNames", overriddenBaseNames.str()) + ("isImplemented", implemented) + ("body", bodyStr) + .render(); + } + return overriddenFunctions.str(); +} + +string SolContract::interfaceOverrideStr() const +{ + ostringstream overriddenFunctions; + for (auto &f: m_overriddenInterfaceFunctions) + { + string bodyStr = Whiskers(R"( + { + return ; + })") + ("uint", f.second[0]->returnValue()) + .render(); + + bool implemented = f.second[0]->implemented(); + + ostringstream overriddenBaseNames; + if (f.second.size() > 1) + { + string sep{}; + for (auto &b: f.second) + { + overriddenBaseNames << Whiskers(R"()") + ("sep", sep) + ("name", b->baseName()) + .render(); + if (sep.empty()) + sep = ", "; + } + } + else + { + assertThrow( + f.second.size() == 1, + langutil::FuzzerError, + "Inconsistent override map" + ); + if (!f.second[0]->explicitlyInherited()) + continue; + } + overriddenFunctions << Whiskers(R"( + function () external + override() returns (uint);)") + ("functionName", f.first->name()) + ("stateMutability", functionMutability(f.first->mutability())) + ("multiple", f.second.size() > 1) + ("baseNames", overriddenBaseNames.str()) + ("isImplemented", implemented) + ("body", bodyStr) + .render(); + } + return overriddenFunctions.str(); +} + string SolContract::str() const { - return ""; + ostringstream bases; + for (auto &b: m_baseContracts) + bases << b->str(); + + ostringstream functions; + for (auto &f: m_contractFunctions) + functions << f->str(); + + functions << interfaceOverrideStr() << contractOverrideStr(); + + return Whiskers(R"( + +abstract contract { + +})") + ("bases", bases.str()) + ("isAbstract", abstract()) + ("contractName", name()) + ("functions", functions.str()) + .render(); } SolContract::SolContract( @@ -662,50 +1068,25 @@ pair SolLibrary::pseudoRandomTest() return pair(chosenFunction, m_publicFunctionMap[chosenFunction]); } -CFunctionOverride::CFunctionOverrideType CFunctionOverride::functionType() const -{ - if (holds_alternative>(m_function.second)) - return CFunctionOverrideType::CONTRACT; - solAssert(interfaceFunction(), "Sol proto fuzzer: Invalid override function type"); - return CFunctionOverrideType::INTERFACE; -} - string CFunctionOverride::name() const { - if (holds_alternative>(m_function.second)) - return get>(m_function.second)->name(); - solAssert(interfaceFunction(), "Sol proto fuzzer: Invalid override function type"); - return get>(m_function.second)->name(); -} - -bool CFunctionOverride::interfaceFunction() const -{ - return functionType() == CFunctionOverrideType::INTERFACE; -} - -bool CFunctionOverride::contractFunction() const -{ - return functionType() == CFunctionOverrideType::CONTRACT; + return m_baseFunction->name(); } SolFunctionVisibility CFunctionOverride::visibility() const { - if (contractFunction()) - return get>(m_function.second)->visibility(); - solAssert(interfaceFunction(), "Sol proto fuzzer: Invalid override function type"); - return SolFunctionVisibility::EXTERNAL; + return m_baseFunction->visibility(); } SolFunctionStateMutability CFunctionOverride::mutability() const { - if (contractFunction()) - return get>(m_function.second)->mutability(); - solAssert(interfaceFunction(), "Sol proto fuzzer: Invalid override function type"); - return get>(m_function.second)->mutability(); + return m_baseFunction->mutability(); } string CFunctionOverride::str() const { + solAssert(virtualized() || !implemented(), "Sol proto fuzzer: Invalid virtualization of contract function override"); + string bodyStr = Whiskers(R"( { return ; @@ -717,7 +1098,7 @@ string CFunctionOverride::str() const function () override virtual returns (uint);)") ("functionName", name()) - ("isVirtual", virtualized() || !implemented()) + ("isVirtual", virtualized()) ("visibility", functionVisibility(visibility())) ("stateMutability", functionMutability(mutability())) ("body", bodyStr) @@ -725,37 +1106,10 @@ string CFunctionOverride::str() const .render(); } -//string CFunctionOverride::commaSeparatedBaseNames() -//{ -// ostringstream baseNames; -// string separator{}; -// for (auto &override: m_function) -// { -// auto base = override.first; -// string baseName; -// if (auto b = get(base)) -// baseName = b->name(); -// else -// baseName = get(base)->name(); -// -// baseNames << Whiskers(R"()") -// ("sep", separator) -// ("base", baseName) -// .render(); -// if (separator.empty()) -// separator = ", "; -// } -// return baseNames.str(); -//} - -//string CFunctionOverride::baseName() const -//{ -// auto base = m_function.first; -// if (contractFunction()) -// return get>(base)->name(); -// solAssert(interfaceFunction(), "Sol proto fuzzer: Invalid override function type"); -// return get>(base)->name(); -//} +string CFunctionOverride::baseName() const +{ + return m_baseContract->name(); +} IFunctionOverride::IFunctionOverride( std::shared_ptr _baseInterface, diff --git a/test/tools/ossfuzz/SolProtoAdaptor.h b/test/tools/ossfuzz/SolProtoAdaptor.h index 8309ec563..b4b0adaf8 100644 --- a/test/tools/ossfuzz/SolProtoAdaptor.h +++ b/test/tools/ossfuzz/SolProtoAdaptor.h @@ -115,10 +115,12 @@ struct SolContractFunction ContractFunction const& _function, std::string _contractName, std::string _functionName, + bool _implement, std::string _returnValue ); bool operator==(SolContractFunction const& _rhs) const; bool operator!=(SolContractFunction const& _rhs) const; + bool disallowed() const; std::string str() const; std::string name() const @@ -133,6 +135,10 @@ struct SolContractFunction { return m_virtual; } + bool implemented() const + { + return m_implemented; + } std::string returnValue() const { return m_returnValue; @@ -152,6 +158,7 @@ struct SolContractFunction SolFunctionStateMutability m_mutability = SolFunctionStateMutability::PURE; bool m_virtual = false; std::string m_returnValue; + bool m_implemented = true; }; struct SolLibraryFunction @@ -235,9 +242,28 @@ struct SolLibrary struct SolBaseContract { + enum BaseType + { + INTERFACE, + CONTRACT + }; + SolBaseContract(ProtoBaseContract _base, std::string _name, std::shared_ptr _prng); - BaseContracts m_base; + std::variant>, std::vector>> + baseFunctions(); + BaseType type() const; + std::string str(); + std::shared_ptr interface() + { + return std::get>(m_base); + } + std::shared_ptr contract() + { + return std::get>(m_base); + } + + std::variant, std::shared_ptr> m_base; std::string m_baseName; std::shared_ptr m_prng; }; @@ -247,17 +273,33 @@ struct SolContract SolContract(Contract const& _contract, std::string _name, std::shared_ptr _prng); std::string str() const; + std::string interfaceOverrideStr() const; + std::string contractOverrideStr() const; void addFunctions(Contract const& _contract); void addBases(Contract const& _contract); void addOverrides(); - void overrideHelper(); + void interfaceFunctionOverride( + std::shared_ptr _base, + std::shared_ptr _function + ); + void contractFunctionOverride( + std::shared_ptr _base, + std::shared_ptr _function + ); + bool validTest() const; + std::tuple validContractTest(); std::tuple pseudoRandomTest(); unsigned randomNumber() const { return m_prng->operator()(); } + bool coinToss() const + { + return randomNumber() % 2 == 0; + } + std::string name() const { return m_contractName; @@ -295,7 +337,8 @@ struct SolContract std::string m_lastBaseName; std::vector> m_contractFunctions; std::vector> m_baseContracts; - std::vector> m_overriddenFunctions; + std::map, std::vector>> m_overriddenContractFunctions; + std::map, std::vector>> m_overriddenInterfaceFunctions; /// Maps non abstract contract name to list of publicly exposed function name /// and their expected output std::map> m_contractFunctionMap; @@ -320,7 +363,7 @@ struct SolInterface return m_prng->operator()(); } - bool coinFlip() const + bool coinToss() const { return randomNumber() % 2 == 0; } @@ -396,42 +439,36 @@ struct SolInterface struct CFunctionOverride { - CFunctionOverride( - BaseContracts _base, - OverrideFunction _function, - bool _implemented, - bool _virtualized, - bool _redeclared, - std::string _returnValue - ) - { - m_function = std::make_pair(_base, std::move(_function)); - m_implemented = _implemented; - m_virtualized = _virtualized; - m_redeclared = _redeclared; - m_returnValue = _returnValue; - } - enum class DerivedType { ABSTRACTCONTRACT, CONTRACT }; - enum class CFunctionOverrideType + CFunctionOverride( + std::shared_ptr _base, + std::shared_ptr _function, + SolContract* _derived, + bool _implemented, + bool _virtualized, + bool _explicitInheritance, + std::string _returnValue + ) { - INTERFACE, - CONTRACT - }; + m_baseContract = _base; + m_baseFunction = _function; + m_derivedProgram = _derived; + m_implemented = _implemented; + m_virtualized = _virtualized; + m_explicitlyInherited = _explicitInheritance; + m_returnValue = _returnValue; + m_derivedType = _derived->abstract() ? DerivedType::ABSTRACTCONTRACT : DerivedType::CONTRACT; + } std::string str() const; std::string name() const; - CFunctionOverrideType functionType() const; - - bool interfaceFunction() const; - bool contractFunction() const; SolFunctionVisibility visibility() const; @@ -442,17 +479,30 @@ struct CFunctionOverride std::string baseName() const; - /// Overridden function - OverrideCFunction m_function; - /// Flag that is true if overridden function is implemented - bool m_implemented = true; - /// Flag that is true if overridden function is marked virtual + std::shared_ptr baseContract() const + { + return m_baseContract; + } + + std::shared_ptr baseFunction() const + { + return m_baseFunction; + } + + std::shared_ptr m_baseContract; + std::shared_ptr m_baseFunction; + SolContract* m_derivedProgram; + + /// Flag that is true if overridden function is implemented in derived contract + bool m_implemented = false; + /// Flag that is true if overridden function implemented in derived contract is + /// marked virtual bool m_virtualized = false; /// Flag that is true if overridden function is redeclared but not implemented - bool m_redeclared = false; - /// The uint value to be returned by the overridden function if it is - /// implemented + bool m_explicitlyInherited = false; + /// The uint value to be returned if the overridden interface function is implemented std::string m_returnValue; + DerivedType m_derivedType; bool implemented() const { @@ -464,9 +514,9 @@ struct CFunctionOverride return m_virtualized; } - bool redeclared() const + bool explicitlyInherited() const { - return m_redeclared; + return m_explicitlyInherited; } std::string returnValue() const @@ -518,6 +568,21 @@ struct IFunctionOverride std::string interfaceStr() const; std::string contractStr() const; + void setImplement() + { + m_implemented = true; + } + + void setVirtual() + { + m_virtualized = true; + } + + void setExplicitInherit() + { + m_explicitlyInherited = true; + } + bool implemented() const { return m_implemented; diff --git a/test/tools/ossfuzz/protoToSol.cpp b/test/tools/ossfuzz/protoToSol.cpp index 3c6114d80..66828cf26 100644 --- a/test/tools/ossfuzz/protoToSol.cpp +++ b/test/tools/ossfuzz/protoToSol.cpp @@ -76,7 +76,6 @@ string ProtoConverter::visit(TestContract const& _testContract) testCode = Whiskers(R"( return 0;)") .render(); -#if 0 else { auto testTuple = pseudoRandomContractTest(); @@ -90,7 +89,6 @@ string ProtoConverter::visit(TestContract const& _testContract) ("expectedOutput", get<2>(testTuple)) .render(); } -#endif break; } @@ -146,8 +144,7 @@ string ProtoConverter::visit(ContractType const& _contractType) case ContractType::kC: m_mostDerivedAbstractContract = _contractType.c().abstract(); m_mostDerivedProgram = MostDerivedProgram::CONTRACT; -// return visit(_contractType.c()); - return ""; + return visit(_contractType.c()); case ContractType::kL: m_mostDerivedProgram = MostDerivedProgram::LIBRARY; return visit(_contractType.l()); @@ -159,45 +156,6 @@ string ProtoConverter::visit(ContractType const& _contractType) } } -string ProtoConverter::visit(ContractOrInterface const& _contractOrInterface) -{ - switch (_contractOrInterface.contract_or_interface_oneof_case()) - { - case ContractOrInterface::kC: -// return visit(_contractOrInterface.c()); - return ""; - case ContractOrInterface::kI: -// return visit(_contractOrInterface.i()); - return ""; - case ContractOrInterface::CONTRACT_OR_INTERFACE_ONEOF_NOT_SET: - return ""; - } -} - -bool ProtoConverter::contractFunctionImplemented( - Contract const* _contract, - CIFunc _function -) -{ - auto v = m_contractFunctionMap[_contract]; - for (auto &e: v) - if (get<0>(e) == _function) - return get<1>(e); - return false; -} - -bool ProtoConverter::contractFunctionVirtual( - Contract const* _contract, - CIFunc _function -) -{ - auto v = m_contractFunctionMap[_contract]; - for (auto &e: v) - if (get<0>(e) == _function) - return get<2>(e); - return false; -} - #if 0 string ProtoConverter::mostDerivedInterfaceOverrides(Interface const& _interface) { @@ -721,23 +679,6 @@ unsigned ProtoConverter::randomNumber() } #if 0 -bool ProtoConverter::disallowedContractFunction(SolContractFunction const& _contractFunction, bool _isVirtual) -{ - string visibility = functionVisibility(_contractFunction.m_visibility); - string mutability = functionMutability(_contractFunction.m_mutability); - - // Private virtual functions are disallowed - if (visibility == "private" && _isVirtual) - return true; - // Private payable functions are disallowed - else if (visibility == "private" && mutability == "payable") - return true; - // Internal payable functions are disallowed - else if (visibility == "internal" && mutability == "payable") - return true; - return false; -} - string ProtoConverter::functionName(CILFunc _function) { solAssert(m_functionNameMap.count(_function), "Sol proto fuzzer: Unregistered function"); diff --git a/test/tools/ossfuzz/protoToSol.h b/test/tools/ossfuzz/protoToSol.h index ffd3049e3..73cd1b609 100644 --- a/test/tools/ossfuzz/protoToSol.h +++ b/test/tools/ossfuzz/protoToSol.h @@ -77,50 +77,10 @@ private: std::string visit(Program const&); std::string visit(TestContract const&); std::string visit(ContractType const&); - std::string visit(ContractOrInterface const&); std::string visit(Interface const& _interface); - /// Visitor for most derived interface messages. - /// @param _interface is a const reference to interface protobuf message - /// @returns a 3-tuple containing Solidity translation of all base contracts - /// this interface derives from, names of all base contracts, and the Solidity - /// translation of this interface. - std::tuple - visitMostDerivedInterface(Interface const& _interface); - std::string visit(Contract const&); - /// Define overrides for most derived interface. - std::string mostDerivedInterfaceOverrides(Interface const& _interface); - /// Define overrides for most derived contract. - std::string mostDerivedContractOverrides(Interface const& _interface); - std::string traverseOverrides(Contract const&); - std::string registerAndVisitFunction( - CIL _program, - CILFunc _func, - unsigned _index, - bool _override, - bool _virtual, - bool _implement - ); - std::string overrideFunction(CILFunc _function, bool _virtual, bool _implement); - std::pair contractFunctionParams( - Contract const* _contract, - ContractFunction const* _function - ); - std::string visit(CILFunc _function, bool _override, bool _virtual, bool _implement); - std::string visit(Library const&); + std::string visit(Library const& _library); + std::string visit(Contract const& _contract); std::string programName(CIL _program); - std::string createFunctionName(CIL _program, unsigned _index); - std::string functionName(CILFunc _function); - void registerFunctionName(CIL _program, CILFunc _function, unsigned _index); - std::tuple visitProgramHelper(CIL _program); - bool contractFunctionImplemented(Contract const* _contract, CIFunc _function); - bool contractFunctionVirtual(Contract const* _contract, CIFunc _function); - std::tuple mostDerivedContractOverrideParams(); - - std::pair contractFunctionOverrideParams( - Contract const* _base, - Contract const* _derived, - CIFunc _baseFunc - ); std::tuple pseudoRandomLibraryTest(); std::tuple pseudoRandomContractTest(); @@ -156,10 +116,6 @@ private: } unsigned randomNumber(); -#if 0 - static bool disallowedContractFunction(SolContractFunction const& _contractFunction, bool _isVirtual); -#endif - unsigned m_numPrograms = 0; unsigned m_counter = 0; bool m_mostDerivedAbstractContract = false; @@ -167,15 +123,6 @@ private: std::shared_ptr m_randomGen; MostDerivedProgram m_mostDerivedProgram = MostDerivedProgram::CONTRACT; - /// Map whose key is pointer to protobuf interface message - /// and whose value is its contract name - std::map m_interfaceNameMap; - /// Map whose key is pointer to protobuf contract message - /// and whose value is its contract name - std::map m_contractNameMap; - /// Map whose key is library name and whose value is the - /// number of implemented functions in it. - std::map m_libraryFuncMap; /// Map whose key is a const pointer to protobuf contract /// message and whose value is a list of 3-tuples that /// store a const pointer to a protobuf interface or contract @@ -189,21 +136,9 @@ private: /// assigned to it. std::map m_functionNameMap; std::map m_programNameMap; - /// Map whose key is a const pointer to protobuf contract or interface - /// function message type and whose value is a pair of const pointer to - /// protobuf contract or interface it belongs to and its declaration - /// position (which is an unsigned integer that starts from 0). - std::map> m_functionProgramMap; - - std::map>> m_programFunctionNameMap; std::vector> m_libraryTests; std::vector> m_contractTests; std::string m_libraryName; - - static auto constexpr s_interfaceFunctionPrefix = "i"; - static auto constexpr s_libraryFunctionPrefix = "l"; - static auto constexpr s_contractFunctionPrefix = "c"; - static auto constexpr s_functionPrefix = "func"; }; } \ No newline at end of file