diff --git a/test/tools/ossfuzz/SolProtoAdaptor.cpp b/test/tools/ossfuzz/SolProtoAdaptor.cpp index 757d9921c..21fdb9446 100644 --- a/test/tools/ossfuzz/SolProtoAdaptor.cpp +++ b/test/tools/ossfuzz/SolProtoAdaptor.cpp @@ -159,6 +159,12 @@ SolInterfaceFunction::SolInterfaceFunction( m_contractName = _contractName; } +bool SolInterfaceFunction::namesake(SolContractFunction const& _rhs) const +{ + // TODO: Change this once we permit arbitrary function parameter types + return name() == _rhs.name(); +} + bool SolInterfaceFunction::namesake(SolInterfaceFunction const& _rhs) const { // TODO: Change this once we permit arbitrary function parameter types @@ -173,7 +179,7 @@ bool SolInterfaceFunction::operator==(SolInterfaceFunction const& _rhs) const bool SolInterfaceFunction::operator!=(SolInterfaceFunction const& _rhs) const { - solAssert(namesake(_rhs), "Sol proto adaptor: Cannot compare two interface functions with different names"); + solAssert(namesake(_rhs), "Sol proto adaptor: Comparing two interface functions with different names is redundant"); return m_mutability != _rhs.m_mutability; } @@ -238,50 +244,139 @@ string SolInterfaceFunction::str() const return ""; } +string SolContractFunction::overriddenFromBaseNames() const +{ + ostringstream nameStr; + string separator{}; + for (auto &b: m_overriddenFrom) + { + nameStr << separator << b; + if (separator.empty()) + separator = ", "; + } + return nameStr.str(); +} + +void SolContractFunction::merge(SolContractFunction const& _rhs) +{ + assertThrow( + this->operator==(_rhs), + langutil::FuzzerError, + "Sol proto adaptor: Invalid inheritance hierarchy" + ); + m_type = Type::EXPLICITOVERRIDECONTRACT; + for (auto &b: _rhs.m_overriddenFrom) + m_overriddenFrom.push_back(b); +} + +void SolContractFunction::merge(SolInterfaceFunction const& _rhs) +{ + assertThrow( + this->operator==(_rhs), + langutil::FuzzerError, + "Sol proto adaptor: Invalid inheritance hierarchy" + ); + m_type = Type::EXPLICITOVERRIDEINTERFACE; + for (auto &b: _rhs.m_overriddenFrom) + m_overriddenFrom.push_back(b); +} + +SolContractFunction::SolContractFunction( + vector _overriddenFrom, + SolFunctionStateMutability _mutability, + std::string _contractName, + std::string _functionName, + Type _type, + bool _implemented, + bool _virtual, + std::string _returnValue, + SolFunctionVisibility _vis +) +{ + for (auto &s: _overriddenFrom) + m_overriddenFrom.push_back(s); + m_contractName = _contractName; + m_functionName = _functionName; + m_type = _type; + m_implemented = _implemented; + m_returnValue = _returnValue; + m_visibility = _vis; + m_mutability = _mutability; + // Unimplemented contract functions must be marked virtual + if (explicitOverride() || memberFunction()) + { + if (_implemented) + m_virtual = _virtual; + else + m_virtual = true; + } +} + SolContractFunction::SolContractFunction( ContractFunction const& _function, std::string _contractName, std::string _functionName, + Type _type, bool _implemented, std::string _returnValue ) { m_contractName = _contractName; + m_overriddenFrom.push_back(m_contractName); m_functionName = _functionName; m_visibility = visibilityConverter(_function.vis()); m_mutability = mutabilityConverter(_function.mut()); + m_type = _type; m_returnValue = _returnValue; m_implemented = _implemented; // Unimplemented contract functions must be marked virtual - m_virtual = _implemented ? _function.virtualfunc() : true; + if (explicitOverride() || memberFunction()) + { + if (_implemented) + m_virtual = _function.virtualfunc(); + else + m_virtual = true; + } + // TODO: Perhaps not hard fail here. Silently ignoring instead. + assertThrow( + !disallowed(), + langutil::FuzzerError, + "Sol proto adaptor: Invalid parameters for a contract function e.g., private+virtual" + ); +} + +bool SolContractFunction::namesake(SolContractFunction const& _rhs) const +{ + return name() == _rhs.name(); +} + +bool SolContractFunction::namesake(SolInterfaceFunction const& _rhs) const +{ + return name() == _rhs.name(); } bool SolContractFunction::operator==(SolContractFunction const& _rhs) const { - // TODO: Consider function parameters in addition to name once they are - // implemented. - return name() == _rhs.name(); + solAssert(namesake(_rhs), "Sol proto adaptor: Cannot compare two contract functions with different names"); + return m_mutability == _rhs.m_mutability && m_visibility == _rhs.m_visibility; } bool SolContractFunction::operator!=(SolContractFunction const& _rhs) const { - // TODO: Consider function parameters in addition to name once they are - // implemented. - return name() != _rhs.name(); + solAssert(namesake(_rhs), "Sol proto adaptor: Comparing two contract functions with different names is redundant"); + return m_mutability != _rhs.m_mutability || m_visibility != _rhs.m_visibility; } bool SolContractFunction::operator==(SolInterfaceFunction const& _rhs) const { - // TODO: Consider function parameters in addition to name once they are - // implemented. - return name() == _rhs.name(); + solAssert(namesake(_rhs), "Sol proto adaptor: Cannot compare a contract function with a differently named interface function"); + return m_mutability == _rhs.m_mutability && m_visibility == SolFunctionVisibility::EXTERNAL; } bool SolContractFunction::operator!=(SolInterfaceFunction const& _rhs) const { - // TODO: Consider function parameters in addition to name once they are - // implemented. - return name() != _rhs.name(); + solAssert(namesake(_rhs), "Sol proto adaptor: Cannot compare a contract function with a differently named interface function"); + return m_mutability != _rhs.m_mutability || m_visibility != SolFunctionVisibility::EXTERNAL; } bool SolContractFunction::disallowed() const @@ -300,9 +395,16 @@ bool SolContractFunction::disallowed() const string SolContractFunction::str() const { - if (disallowed()) + if (implicitOverride()) return ""; + bool override = false; + bool multiOverride = false; + if (explicitOverride()) + { + override = true; + multiOverride = m_overriddenFrom.size() > 1; + } string bodyStr = Whiskers(R"( { return ; @@ -312,13 +414,17 @@ string SolContractFunction::str() const return Whiskers(R"( function () virtual + override() returns (uint);)") ("functionName", name()) ("isVirtual", isVirtual()) ("visibility", functionVisibility(visibility())) ("stateMutability", functionMutability(mutability())) - ("body", bodyStr) + ("isOverride", override) + ("isMultiple", multiOverride) + ("baseNames", overriddenFromBaseNames()) ("isImplemented", implemented()) + ("body", bodyStr) .render(); } @@ -354,111 +460,6 @@ string SolLibraryFunction::str() const .render(); } -#if 0 -unsigned SolBaseContract::functionIndex() -{ - if (type() == BaseType::INTERFACE) - return interface()->functionIndex(); - else - { - solAssert(type() == BaseType::CONTRACT, "Sol proto adaptor: Invalid base contract"); - return contract()->functionIndex(); - } -} - -string SolBaseContract::lastBaseName() -{ - if (type() == BaseType::INTERFACE) - return interface()->lastBaseName(); - else - { - solAssert(type() == BaseType::CONTRACT, "Sol proto adaptor: Invalid base contract"); - return contract()->lastBaseName(); - } -} - -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(); - } -} - -string SolBaseContract::name() -{ - if (type() == BaseType::INTERFACE) - return interface()->name(); - else - { - solAssert(type() == BaseType::CONTRACT, "Sol proto adaptor: Invalid base contract"); - return contract()->name(); - } -} - -SolBaseContract::SolBaseContract( - ProtoBaseContract _base, - string _name, - shared_ptr _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 InterfaceFunctionAttributes::merge(InterfaceFunctionAttributes const& _rhs) -{ - solAssert(namesake(_rhs), "Sol proto adaptor: Merge called on differently named interface functions"); - assertThrow( - this->operator==(_rhs), - langutil::FuzzerError, - "Sol proto adaptor: Invalid interface inheritance hierarchy" - ); - // Must override - m_override = true; - for (auto &b: _rhs.m_baseNames) - m_baseNames.push_back(b); -} - -bool InterfaceFunctionAttributes::namesake(InterfaceFunctionAttributes const& _rhs) const -{ - return m_name == _rhs.m_name; -} - -bool InterfaceFunctionAttributes::operator==(InterfaceFunctionAttributes const& _rhs) const -{ - return namesake(_rhs) && (m_mutability == _rhs.m_mutability); -} - -bool InterfaceFunctionAttributes::operator!=(InterfaceFunctionAttributes const& _rhs) const -{ - return !namesake(_rhs) || (m_mutability != _rhs.m_mutability); -} -#endif - void SolInterface::merge() { /* Merge algorithm: @@ -610,105 +611,77 @@ interface is { .render(); } -#if 0 -SolFunction::Type SolFunction::operator()(FunctionVariant _var) const +unsigned SolBaseContract::functionIndex() { - if (holds_alternative>(_var)) - return SolFunction::Type::INTERFACE; + if (type() == BaseType::INTERFACE) + return interface()->functionIndex(); else { - solAssert(holds_alternative>(_var), "Sol proto adaptor: Invalid Sol function"); - return SolFunction::Type::CONTRACT; + solAssert(type() == BaseType::CONTRACT, "Sol proto adaptor: Invalid base contract"); + return contract()->functionIndex(); } } -bool ContractFunctionAttributes::namesake(ContractFunctionAttributes const& _attr) const +string SolBaseContract::lastBaseName() { - return m_name == _attr.m_name; -} - -bool ContractFunctionAttributes::operator==(ContractFunctionAttributes const& _rhs) const -{ - return m_mutability == _rhs.m_mutability && m_visibility == _rhs.m_visibility; -} - -bool ContractFunctionAttributes::operator!=(ContractFunctionAttributes const& _rhs) const -{ - return m_mutability != _rhs.m_mutability || m_visibility != _rhs.m_visibility; -} - -void ContractFunctionAttributes::merge(ContractFunctionAttributes const& _rhs) -{ - assertThrow( - namesake(_rhs), - langutil::FuzzerError, - "Sol proto adaptor: Differently named functions cannot be merged" - ); - assertThrow( - this->operator==(_rhs), - langutil::FuzzerError, - "Sol proto adaptor: Namesake functions with different visibility and/or state mutability cannot be merged" - ); - // Must override since more than one inherited bases defines - // identical function with identical visibility and/or state - // mutability. - m_override = true; - // Add base to override base list - for (auto &b: _rhs.m_bases) - m_bases.push_back(b); -} - -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_functions) - for (auto &lbf: _base2->interface()->m_functions) - assertThrow( - (bf != lbf) || (bf->mutability() == lbf->mutability()), - 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_functions) - for (auto &lbf: _base2->contract()->m_contractFunctions) - if (bf != lbf || - ((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_functions) - 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" - ); - } + if (type() == BaseType::INTERFACE) + return interface()->lastBaseName(); else { - for (auto &bf: _base1->contract()->m_contractFunctions) - for (auto &lbf: _base2->contract()->m_contractFunctions) - assertThrow( - bf != lbf || (bf->mutability() == lbf->mutability() && bf->visibility() == lbf->visibility()), - langutil::FuzzerError, - "Sol proto adaptor: New base defines namesake function with different " - "visibility and/or state mutability" - ); + solAssert(type() == BaseType::CONTRACT, "Sol proto adaptor: Invalid base contract"); + return contract()->lastBaseName(); + } +} + +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(); + } +} + +string SolBaseContract::name() +{ + if (type() == BaseType::INTERFACE) + return interface()->name(); + else + { + solAssert(type() == BaseType::CONTRACT, "Sol proto adaptor: Invalid base contract"); + return contract()->name(); + } +} + +SolBaseContract::SolBaseContract( + ProtoBaseContract _base, + string _name, + shared_ptr _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) + ); } } @@ -725,51 +698,25 @@ string SolContract::baseNames() const return bases.str(); } -bool SolContract::validTest() const +bool SolContract::validTest() { - // 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; + return m_contractFunctionMap[name()].size() > 0; } tuple SolContract::validContractTest() { - string chosenContractName{}; + string chosenContractName = name(); string chosenFunctionName{}; string expectedOutput{}; - unsigned numContracts = m_contractFunctionMap.size(); - unsigned contractIdx = random() % numContracts; - unsigned functionIdx = 0; + unsigned functionIdx = random() % m_contractFunctionMap[name()].size(); unsigned mapIdx = 0; - for (auto &e: m_contractFunctionMap) + for (auto &e: m_contractFunctionMap[name()]) { - if (contractIdx == mapIdx) + if (functionIdx == mapIdx) { - // 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 - { - chosenContractName = e.first; - functionIdx = random() % e.second.size(); - unsigned functionMapIdx = 0; - for (auto &f: e.second) - { - if (functionIdx == functionMapIdx) - { - chosenFunctionName = f.first; - expectedOutput = f.second; - break; - } - functionMapIdx++; - } - break; - } + chosenFunctionName = e.first; + expectedOutput = e.second; + break; } mapIdx++; } @@ -784,338 +731,10 @@ tuple SolContract::pseudoRandomTest() 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_overriddenFunctions) - { - if (holds_alternative>(m.first)) - - // 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; -#if 1 - std::cout << "Explicitly overriding interface " << - _function->name() << - " of " << - _base->name() << - " from " << - name() << - std::endl; -#endif - 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_overriddenFunctions.insert( - pair( - _function, - vector>{ - make_shared( - CFunctionOverride( - _base, - _function, - this, - implement, - virtualize, - explicitOverride, - newReturnValue() - ) - ) - } - ) - ); -#if 1 - std::cout << (explicitOverride ? "Explicitly" : "Implicitly") << - " overriding interface " << - _function->name() << - " of " << - _base->name() << - " from " << - name() << - std::endl; -#endif - } -} - -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() - ) - ) - ) - ); -#if 1 - std::cout << "Explicitly overriding contract " << - _function->name() << - " of " << - _base->name() << - " from " << - name() << - std::endl; -#endif - 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() - ) - ) - } - ) - ); -#if 1 - std::cout << (explicitOverride ? "Explicitly" : "Implicitly") << - " overriding contract " << - _function->name() << - " of " << - _base->name() << - " from " << - name() << - std::endl; -#endif - } -} - -void SolContract::merge(shared_ptr _interface) -{ - /* If abstract contract, we may override interface functions - * If non abstract contract, we must override them - */ - if (m_abstract) - { - for (_interface->m_) - } - else - { - - } - -} - -void SolContract::merge(shared_ptr _base) -{ - if (_base->type() == SolBaseContract::INTERFACE) - merge(_base->interface()); - else - merge(_base->contract()); -} - -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_functions) - { - interfaceFunctionOverride(base->interface(), f); - } - // Override interface implicit and explicit overrides - for (auto &m: base->interface()->m_overrideMap) - { - solAssert(m.second.size() >= 1, "Sol proto adaptor: Inconsistent interface override map"); - if (m.second.size() == 1) - { - if (m.second[0]->explicitlyInherited()) - interfaceFunctionOverride(base->interface(), m.first); - else - interfaceFunctionOverride(m.second[0]->m_baseInterface, m.first); - } - else - { - interfaceFunctionOverride(base->interface(), m.first); - } - } - } - else - { - solAssert(base->type() == SolBaseContract::BaseType::CONTRACT, "Sol proto fuzzer: Base contract neither interface nor contract"); - // Override virtual contract functions - for (auto &f: base->contract()->m_contractFunctions) - { - // Override well-defined virtual functions only - // Well defined means that they are not explicitly disallowed - // See SolContractFunction::disallowed() for what is disallowed. - if (!f->disallowed() && f->isVirtual()) - contractFunctionOverride(base->contract(), f); - } - // Override contract overrides only if they are virtual. - for (auto &m: base->contract()->m_overriddenContractFunctions) - { - if (!m.first->disallowed()) - for (auto &b: m.second) - if (b->virtualized()) - contractFunctionOverride(b->m_baseContract, m.first); - } - // Override implicit contract overrides from base interface only if - // - They have been implicitly overridden by base contract OR - // - They have been explicitly overridden and virtualized but unimplemented - for (auto &m: base->contract()->m_overriddenInterfaceFunctions) - { - std::cout << "Overriding " << m.first->name() << " from " << name() << std::endl; - if (m.second.size() == 1) - { - if (!m.second[0]->explicitlyInherited()) - interfaceFunctionOverride(m.second[0]->m_baseInterface, m.first); -// else if (m.second[0]->virtualized() && !m.second[0]->implemented()) -// interfaceFunctionOverride(base, m.first); - } - } - } - } - // If any of the interface overrides has same name as one of the contract overrides - // but they differ in state mutability and/or visibility, we throw to signal invalid - // contract. -// for (auto &c: m_overriddenContractFunctions) -// for (auto &i: m_overriddenInterfaceFunctions) -// if (i.first->name() == c.first->name() && ((i.first->mutability() != c.first->mutability()) || -// c.first->visibility() != SolFunctionVisibility::EXTERNAL)) -// assertThrow( -// false, -// langutil::FuzzerError, -// "Sol proto fuzzer: Interface and contract overrides have same name but " -// "different visibility and/or state mutability." -// ); -} - 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()) { @@ -1124,11 +743,12 @@ void SolContract::addFunctions(Contract const& _contract) f, contractName, newFunctionName(), + SolContractFunction::Type::MEMBERFUNCTION, (abs ? coinToss() : true), newReturnValue() ) ); - m_contractFunctions.push_back(function); + m_functions.push_back(function); // If contract is not abstract, add its public and external // functions to contract function map. if (!abs) @@ -1147,6 +767,426 @@ void SolContract::addFunctions(Contract const& _contract) } } +void SolContract::merge() +{ + /* Merge algorithm: + * 1. Deep copy all base interface functions (local) into a single list (global) + * 2. Mark all of these as implicit overrides + * 3. Iterate list of implicit overrides + * 3a. If n-way merge is necessary, do so and mark a two-base explicit override and add to contract + * 3b. If n-way merge is not possible, add as implicit override to contract + * 4. Update ownership of n-way merges + * 5. Iterate list of contract implicit and explicit (2-way) overrides + * 5a. If implicit, pseudo randomly mark it explicit + */ + FunctionList global{}; + // Step 1-2 + for (auto& base: m_baseContracts) { + auto baseType = base->type(); + solAssert( + baseType == SolBaseContract::BaseType::INTERFACE || baseType == SolBaseContract::BaseType::CONTRACT, + "Sol proto adaptor: Invalid base contract" + ); + FunctionList local{}; + if (baseType == SolBaseContract::BaseType::INTERFACE) + for (auto& f: base->interface()->m_functions) + local.push_back(make_shared(*f)); + else + // Contract functions may be implicitly inherited + // interface function or contract function. + for (auto& f: base->contract()->m_functions) { + if (holds_alternative>(f)) { + local.push_back( + make_shared( + *get>(f) + ) + ); + } else { + local.push_back( + make_shared( + *get>(f) + ) + ); + } + } + + for (auto& item: local) { + if (holds_alternative>(item)) { + auto function = get>(item); + // Reset override history for past n-way merge + if (function->explicitOverride() && function->numOverriddenFromBases() > 1) + function->resetOverriddenBases(); + // Mark interface function as an implicit override + function->markImplicitOverride(); + global.push_back(item); + } else { + auto function = get>(item); + // Reset override history for past n-way merge + if (function->explicitOverride() && function->numOverriddenFromBases() > 1) + function->resetOverriddenBases(); + if (!function->implicitOverride()) + function->markImplicitContractOverride(); + global.push_back(item); + } + } + } + // Step 3 + FunctionList updateList; + for (auto& functionInBaseContract: global) { +#if 0 + std::cout << "Processing " << f->name() << " from " << f->m_contractName << std::endl; +#endif + bool merged = false; + shared_ptr mergedContract; + for (auto& functionInContract: m_functions) { + if (holds_alternative>(functionInContract)) { + auto function = get>(functionInContract); + // Merge interface into another interface and create a new contract function + if (holds_alternative>(functionInBaseContract)) { + auto g = get>(functionInBaseContract); + if (function->namesake(*g)) { +#if 0 + std::cout << "Interface function merged into interface function" << std::endl; + std::cout << "n-way merge of " << g->name() << " from " << g->m_contractName << std::endl; +#endif + function->merge(*g); + // Create new contract function + mergedContract = make_shared( + SolContractFunction( + function->m_overriddenFrom, + function->mutability(), + name(), + function->name(), + SolContractFunction::Type::EXPLICITOVERRIDEINTERFACE, + abstract() ? coinToss() : true, + coinToss(), + newReturnValue() + ) + ); + // Erase merged interface function + auto pos = find(m_functions.begin(), m_functions.end(), functionInContract); + m_functions.erase(pos); + m_functions.insert(pos, mergedContract); + merged = true; + break; + } + } + // Merge contract function into interface function + else { + auto g = get>(functionInBaseContract); + if (function->namesake(*g)) { +#if 0 + std::cout << "Contract function merged into interface function" << std::endl; + std::cout << "n-way merge of " << g->name() << " from " << g->m_contractName << std::endl; +#endif + // Assert contract function is virtual + assertThrow( + g->isVirtual(), + langutil::FuzzerError, + "Sol proto fuzzer: n-way merge of non-virtual contract function is not possible" + ); + // Merge interface into contract instead of the other way round + g->merge(*function); + // Create new contract function + mergedContract = make_shared( + SolContractFunction( + g->m_overriddenFrom, + g->mutability(), + name(), + g->name(), + SolContractFunction::Type::EXPLICITOVERRIDECONTRACT, + abstract() ? coinToss() : true, + coinToss(), + newReturnValue() + ) + ); + // Erase merged interface function + auto pos = find(m_functions.begin(), m_functions.end(), functionInContract); + m_functions.erase(pos); + m_functions.insert(pos, mergedContract); + merged = true; + break; + } + } + } + // Merge interface/contract into contract + else { + auto function = get>(functionInContract); + // Merge interface into contract function + if (holds_alternative>(functionInBaseContract)) { + auto g = get>(functionInBaseContract); + if (function->namesake(*g)) { +#if 0 + std::cout << "Interface function merged into contract function" << std::endl; + std::cout << "n-way merge of " << g->name() << " from " << g->m_contractName << std::endl; +#endif + // Assert contract function is virtual + assertThrow( + function->isVirtual(), + langutil::FuzzerError, + "Sol proto fuzzer: n-way merge of non-virtual contract function is not possible" + ); + function->merge(*g); +#if 0 + std::cout << "Overridden from " << function->overriddenFromBaseNames() << std::endl; +#endif + // Create new contract function + mergedContract = make_shared( + SolContractFunction( + function->m_overriddenFrom, + function->mutability(), + name(), + function->name(), + SolContractFunction::Type::EXPLICITOVERRIDECONTRACT, + abstract() ? coinToss() : true, + coinToss(), + newReturnValue() + ) + ); + // Erase merged interface function + auto pos = find(m_functions.begin(), m_functions.end(), functionInContract); + m_functions.erase(pos); + m_functions.insert(pos, mergedContract); + merged = true; + break; + } + } + // Merge contract function into contract function + else { + auto g = get>(functionInBaseContract); + if (function->namesake(*g)) { +#if 0 + std::cout << "Contract function merged into contract function" << std::endl; + std::cout << "n-way merge of " << g->name() << " from " << g->m_contractName << std::endl; +#endif + // Assert contract functions are virtual + assertThrow( + g->isVirtual() && function->isVirtual(), + langutil::FuzzerError, + "Sol proto fuzzer: n-way merge of non-virtual contract function is not possible" + ); + function->merge(*g); + // Create new contract function + mergedContract = make_shared( + SolContractFunction( + function->m_overriddenFrom, + function->mutability(), + name(), + function->name(), + SolContractFunction::Type::EXPLICITOVERRIDECONTRACT, + abstract() ? coinToss() : true, + coinToss(), + newReturnValue() + ) + ); + // Erase merged interface function + auto pos = find(m_functions.begin(), m_functions.end(), functionInContract); + m_functions.erase(pos); + m_functions.insert(pos, mergedContract); + merged = true; + break; + } + } + } + } + if (!merged) + m_functions.push_back(functionInBaseContract); + } + // Step 4 + for (auto& u: updateList) { + if (holds_alternative>(u)) + get>(u)->m_contractName = name(); + else + get>(u)->m_contractName = name(); + } + // Step 5: + for (auto& e: m_functions) + { + // All implicitly inherited interface functions must be explicitly inherited + // and implemented if not abstract. + if (holds_alternative>(e)) + { + auto t = get>(e); + if (t->implicitOverride()) + { +#if 0 + std::cout << "Explicitly overriding " << t->name() << " from " << t->m_contractName << std::endl; +#endif + auto pos = find(m_functions.begin(), m_functions.end(), e); + auto contractOverride = make_shared( + SolContractFunction( + {name()}, + t->mutability(), + name(), + t->name(), + SolContractFunction::Type::EXPLICITOVERRIDEINTERFACE, + abstract() ? coinToss() : true, + coinToss(), + newReturnValue() + ) + ); +#if 0 + std::cout << "New function basenames are " << contractOverride->overriddenFromBaseNames() << std::endl; +#endif + m_functions.erase(pos); +#if 0 + std::cout << "Size of function list after erase " << m_functions.size() << std::endl; +#endif + m_functions.insert(pos, contractOverride); +#if 0 + std::cout << "Size of function list after insert " << m_functions.size() << std::endl; +#endif + } + } + else + { + auto t = get>(e); + if (t->implicitOverride() && t->isVirtual()) + { + // If not abstract, all unimplemented functions must be implemented + if (!abstract()) + { + if (!t->implemented()) + { + // This function must be from an abstract contract + // Create a new contract function with an implementation + auto contractOverride = make_shared( + SolContractFunction( + {name()}, + t->mutability(), + name(), + t->name(), + SolContractFunction::Type::EXPLICITOVERRIDECONTRACT, + true, + coinToss(), + newReturnValue(), + t->visibility() + ) + ); + auto pos = find(m_functions.begin(), m_functions.end(), e); + m_functions.erase(pos); + m_functions.insert(pos, contractOverride); + } + // Implemented virtual base contract function + else + { + if (coinToss()) + { + // Reimplement + auto contractOverride = make_shared( + SolContractFunction( + {name()}, + t->mutability(), + name(), + t->name(), + SolContractFunction::Type::EXPLICITOVERRIDECONTRACT, + true, + coinToss(), + newReturnValue(), + t->visibility() + ) + ); + auto pos = find(m_functions.begin(), m_functions.end(), e); + m_functions.erase(pos); + m_functions.insert(pos, contractOverride); + } + } + } + // Abstract contract + else + { + // Virtual implemented base + if (t->implemented()) + { + // If we are explicitly overriding an implemented contract function + // we must implement it. + if (coinToss()) + { + auto contractOverride = make_shared( + SolContractFunction( + {name()}, + t->mutability(), + name(), + t->name(), + SolContractFunction::Type::EXPLICITOVERRIDECONTRACT, + true, + coinToss(), + newReturnValue(), + t->visibility() + ) + ); + auto pos = find(m_functions.begin(), m_functions.end(), e); + m_functions.erase(pos); + m_functions.insert(pos, contractOverride); + } + } + // Unimplemented base contract function virtual implicit + else + { + // Option 1: do nothing + // Option 2: override and virtualize and not implement + // Option 3: override and implement and optionally virtualize + switch (randomNumber() % 3) + { + case 0: + break; + case 1: + { + auto contractOverride = make_shared( + SolContractFunction( + {name()}, + t->mutability(), + name(), + t->name(), + SolContractFunction::Type::EXPLICITOVERRIDECONTRACT, + false, + true, + "", + t->visibility() + ) + ); + auto pos = find(m_functions.begin(), m_functions.end(), e); + m_functions.erase(pos); + m_functions.insert(pos, contractOverride); + break; + } + case 2: + { + auto contractOverride = make_shared( + SolContractFunction( + {name()}, + t->mutability(), + name(), + t->name(), + SolContractFunction::Type::EXPLICITOVERRIDECONTRACT, + true, + coinToss(), + newReturnValue(), + t->visibility() + ) + ); + auto pos = find(m_functions.begin(), m_functions.end(), e); + m_functions.erase(pos); + m_functions.insert(pos, contractOverride); + break; + } + } + } + } + } + } + } + // Step 6 + if (!abstract()) + for (auto &f: m_functions) + if (holds_alternative>(f)) + { + auto function = get>(f); + if (function->implemented()) + m_contractFunctionMap[name()].insert(pair(function->name(), function->returnValue())); + } +} + void SolContract::addBases(Contract const& _contract) { shared_ptr base; @@ -1167,11 +1207,6 @@ void SolContract::addBases(Contract const& _contract) 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 @@ -1179,124 +1214,7 @@ void SolContract::addBases(Contract const& _contract) m_functionIndex += base->functionIndex(); m_lastBaseName = base->lastBaseName(); } -} - -string SolContract::contractOverrideStr() -{ - ostringstream overriddenFunctions; - for (auto &f: m_overriddenContractFunctions) - { - string returnValue = f.second[0]->returnValue(); - string bodyStr = Whiskers(R"( - { - return ; - })") - ("uint", 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 - { - solAssert(f.second.size() == 1, "Inconsistent override map"); - if (!f.second[0]->explicitlyInherited()) - continue; - } - string functionName = f.first->name(); - 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(); - - if (!abstract()) - m_contractFunctionMap[name()].insert(pair(functionName, returnValue)); - } - - return overriddenFunctions.str(); -} - -string SolContract::interfaceOverrideStr() -{ - ostringstream overriddenFunctions; - - for (auto &f: m_overriddenInterfaceFunctions) - { - string returnValue = f.second[0]->returnValue(); - string bodyStr = Whiskers(R"( - { - return ; - })") - ("uint", returnValue) - .render(); - - // Check override class for implementation and virtualized - // flags and print appropriately. - 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 - { - solAssert(f.second.size() == 1, "Inconsistent override map"); - if (!f.second[0]->explicitlyInherited()) - { - continue; - } - - } - string functionName = f.first->name(); - overriddenFunctions << Whiskers(R"( - function () external virtual - override() returns (uint);)") - ("functionName", f.first->name()) - ("stateMutability", functionMutability(f.first->mutability())) - ("isVirtual", virtualized) - ("multiple", f.second.size() > 1) - ("baseNames", overriddenBaseNames.str()) - ("isImplemented", implemented) - ("body", bodyStr) - .render(); - - if (!abstract()) - m_contractFunctionMap[name()].insert(pair(functionName, returnValue)); - } - return overriddenFunctions.str(); + merge(); } string SolContract::str() @@ -1307,12 +1225,10 @@ string SolContract::str() ostringstream functions; - // Print overridden functions - functions << interfaceOverrideStr() << contractOverrideStr(); - - // Print non-overridden functions - for (auto &f: m_contractFunctions) - functions << f->str(); + // Print functions + for (auto &f: m_functions) + if (holds_alternative>(f)) + functions << get>(f)->str(); return Whiskers(R"( @@ -1338,12 +1254,15 @@ SolContract::SolContract( m_contractName = _name; m_lastBaseName = m_contractName; m_abstract = _contract.abstract(); + // Add contract to contract function map only if the contract + // is not abstract. + if (!m_abstract) + m_contractFunctionMap.insert(pair(m_contractName, map{})); addBases(_contract); - addOverrides(); addFunctions(_contract); } -#endif +// Library implementation void SolLibrary::addFunction(LibraryFunction const& _function) { // Register function name and return value @@ -1417,143 +1336,4 @@ pair SolLibrary::pseudoRandomTest() } solAssert(m_publicFunctionMap.count(chosenFunction), "Sol proto adaptor: Invalid library function chosen"); return pair(chosenFunction, m_publicFunctionMap[chosenFunction]); -} - -#if 0 -string CFunctionOverride::name() const -{ - return m_baseFunction->name(); -} - -SolFunctionVisibility CFunctionOverride::visibility() const -{ - return m_baseFunction->visibility(); -} - -SolFunctionStateMutability CFunctionOverride::mutability() const -{ - 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 ; - })") - ("uint", returnValue()) - .render(); - - return Whiskers(R"( - function () override virtual - returns (uint);)") - ("functionName", name()) - ("isVirtual", virtualized()) - ("visibility", functionVisibility(visibility())) - ("stateMutability", functionMutability(mutability())) - ("body", bodyStr) - ("isImplemented", implemented()) - .render(); -} - -string CFunctionOverride::baseName() const -{ - return m_baseContract->name(); -} - -IFunctionOverride::IFunctionOverride( - std::shared_ptr _baseInterface, - std::shared_ptr _baseFunction, - std::variant _derivedProgram, - bool _implement, - bool _virtual, - bool _explicitInherit, - std::string _returnValue -) -{ - if (std::holds_alternative(_derivedProgram)) - { - auto derived = std::get(_derivedProgram); - m_derivedType = derived->abstract() ? DerivedType::ABSTRACTCONTRACT : DerivedType::CONTRACT; - if (!derived->abstract()) - solAssert( - _explicitInherit && !_returnValue.empty() && _implement, - "Contract overrides base interface function either without" - " implementing it or implictly overrides." - ); - else - if (_explicitInherit) - solAssert( - _virtual || (_implement && !_returnValue.empty()), - "Abstract contract overrides base interface function either" - " without implementing it or without marking it virtual." - ); - } - else - { - solAssert( - holds_alternative(_derivedProgram), - "Derived program neither an interface nor a contract" - ); - m_derivedType = DerivedType::INTERFACE; - if (_explicitInherit) - solAssert( - !_virtual && !_implement && _returnValue.empty(), - "Interface overrides base interface function with invalid parameters." - ); - } - - m_baseInterface = _baseInterface; - m_baseFunction = _baseFunction; - m_derivedProgram = _derivedProgram; - m_implemented = _implement; - m_virtualized = _virtual; - m_explicitlyInherited = _explicitInherit; - m_returnValue = _returnValue; -} - -std::string IFunctionOverride::str() const -{ - switch (m_derivedType) - { - case DerivedType::INTERFACE: - return interfaceStr(); - case DerivedType::ABSTRACTCONTRACT: - case DerivedType::CONTRACT: - return contractStr(); - } -} - -string IFunctionOverride::interfaceStr() const -{ - return Whiskers(R"( - function () external override returns(uint); -)") - ("functionName", m_baseFunction->name()) - ("mutability", functionMutability(m_baseFunction->mutability())) - .render(); -} - -string IFunctionOverride::contractStr() const -{ - string bodyStr = Whiskers(R"( - { - return ; - })") - ("uint", returnValue()) - .render(); - - return Whiskers(R"( - function () external override - virtual returns(uint); -)") - ("functionName", m_baseFunction->name()) - ("mutability", functionMutability(m_baseFunction->mutability())) - ("isVirtual", virtualized()) - ("isImplemented", implemented()) - ("body", bodyStr) - .render(); -} -#endif \ No newline at end of file +} \ No newline at end of file diff --git a/test/tools/ossfuzz/SolProtoAdaptor.h b/test/tools/ossfuzz/SolProtoAdaptor.h index a59cbd801..eba400fac 100644 --- a/test/tools/ossfuzz/SolProtoAdaptor.h +++ b/test/tools/ossfuzz/SolProtoAdaptor.h @@ -22,6 +22,7 @@ #include #include #include +#include namespace solidity::test::solprotofuzzer::adaptor { @@ -107,6 +108,7 @@ struct SolInterfaceFunction bool operator!=(SolContractFunction const& _rhs) const; void merge(SolInterfaceFunction const& _rhs); bool namesake(SolInterfaceFunction const& _rhs) const; + bool namesake(SolContractFunction const& _rhs) const; void markExplicitOverride(std::string _contractName); std::string overriddenFromBaseNames() const; @@ -160,17 +162,104 @@ struct SolInterfaceFunction struct SolContractFunction { + enum class Type + { + MEMBERFUNCTION, + IMPLICITOVERRIDECONTRACT, + IMPLICITOVERRIDEINTERFACE, + EXPLICITOVERRIDECONTRACT, + EXPLICITOVERRIDEINTERFACE + }; + SolContractFunction( ContractFunction const& _function, std::string _contractName, std::string _functionName, + Type _type, bool _implement, std::string _returnValue ); + SolContractFunction( + std::vector _overriddenFrom, + SolFunctionStateMutability _mutability, + std::string _contractName, + std::string _functionName, + Type _type, + bool _implement, + bool _virtual, + std::string _returnValue, + SolFunctionVisibility _vis = SolFunctionVisibility::EXTERNAL + ); + + bool memberFunction() const + { + return m_type == Type::MEMBERFUNCTION; + } + bool explicitInterfaceOverride() const + { + return m_type == Type::EXPLICITOVERRIDEINTERFACE; + } + bool explicitContractOverride() const + { + return m_type == Type::EXPLICITOVERRIDECONTRACT; + } + bool implicitInterfaceOverride() const + { + return m_type == Type::IMPLICITOVERRIDEINTERFACE; + } + bool implicitContractOverride() const + { + return m_type == Type::IMPLICITOVERRIDECONTRACT; + } + bool explicitOverride() const + { + return explicitContractOverride() || explicitInterfaceOverride(); + } + bool implicitOverride() const + { + return implicitContractOverride() || implicitInterfaceOverride(); + } + void markImplicitContractOverride() + { + m_type = Type::IMPLICITOVERRIDECONTRACT; + } + void markImplicitInterfaceOverride() + { + m_type = Type::IMPLICITOVERRIDEINTERFACE; + } + void markExplicitContractOverride(std::string _contractName) + { + m_type = Type::EXPLICITOVERRIDECONTRACT; + m_contractName = _contractName; + m_overriddenFrom.clear(); + m_overriddenFrom.push_back(m_contractName); + } + void markExplicitInterfaceOverride(std::string _contractName) + { + m_type = Type::EXPLICITOVERRIDEINTERFACE; + m_contractName = _contractName; + m_overriddenFrom.clear(); + m_overriddenFrom.push_back(m_contractName); + } + std::string overriddenFromBaseNames() const; + unsigned numOverriddenFromBases() const + { + return m_overriddenFrom.size(); + } + void resetOverriddenBases() + { + m_overriddenFrom.clear(); + m_overriddenFrom.push_back(m_contractName); + } + + bool namesake(SolContractFunction const& _rhs) const; + bool namesake(SolInterfaceFunction const& _rhs) const; bool operator==(SolContractFunction const& _rhs) const; bool operator!=(SolContractFunction const& _rhs) const; bool operator==(SolInterfaceFunction const& _rhs) const; bool operator!=(SolInterfaceFunction const& _rhs) const; + void merge(SolContractFunction const& _rhs); + void merge(SolInterfaceFunction const& _rhs); bool disallowed() const; std::string str() const; @@ -210,6 +299,8 @@ struct SolContractFunction bool m_virtual = false; std::string m_returnValue; bool m_implemented = true; + Type m_type; + std::vector m_overriddenFrom; }; struct SolLibraryFunction @@ -226,10 +317,6 @@ struct SolLibraryFunction { return m_functionName; } - std::string libraryName() const - { - return m_libraryName; - } std::string returnValue() const { return m_returnValue; @@ -376,16 +463,15 @@ struct ContractFunctionAttributes struct SolContract { + using FunctionList = std::vector, std::shared_ptr>>; + SolContract( Contract const& _contract, std::string _name, std::shared_ptr _prng ); - void merge(std::shared_ptr _base); - void merge(std::shared_ptr _interface); - void merge(std::shared_ptr _contract); - + void merge(); std::string str(); std::string interfaceOverrideStr(); std::string contractOverrideStr(); @@ -402,7 +488,7 @@ struct SolContract std::shared_ptr _function ); - bool validTest() const; + bool validTest(); std::string baseNames() const; std::tuple validContractTest(); std::tuple pseudoRandomTest(); @@ -443,7 +529,7 @@ struct SolContract } std::string newReturnValue() { - return std::to_string(m_returnValue++); + return std::to_string(randomNumber()); } std::string m_contractName; @@ -451,43 +537,12 @@ struct SolContract unsigned m_functionIndex = 0; unsigned m_returnValue = 0; std::string m_lastBaseName; - std::vector> m_contractFunctions; + FunctionList m_functions; std::vector> m_baseContracts; - std::map, std::shared_ptr>, - std::vector>> m_overriddenFunctions; /// Maps non abstract contract name to list of publicly exposed function name /// and their expected output std::map> m_contractFunctionMap; std::shared_ptr m_prng; - std::vector m_functions; - - -}; - -struct InterfaceFunctionAttributes -{ - InterfaceFunctionAttributes( - std::shared_ptr _function, - bool _override, - std::string _baseName - ) - { - m_name = _function->name(); - m_mutability = _function->mutability(); - m_override = _override; - m_baseNames.push_back(_baseName); - } - InterfaceFunctionAttributes(InterfaceFunctionAttributes const& _rhs); - - void merge(InterfaceFunctionAttributes const& _rhs); - bool namesake(InterfaceFunctionAttributes const& _rhs) const; - bool operator==(InterfaceFunctionAttributes const& _rhs) const; - bool operator!=(InterfaceFunctionAttributes const& _rhs) const; - - SolFunctionStateMutability m_mutability; - std::string m_name; - bool m_override = false; - std::vector m_baseNames; }; struct SolInterface @@ -520,21 +575,6 @@ struct SolInterface return "f" + std::to_string(m_functionIndex++); } - void incrementFunctionIndex() - { - m_functionIndex++; - } - - void resetFunctionIndex() - { - m_functionIndex = 0; - } - - void setFunctionIndex(unsigned _index) - { - m_functionIndex = _index; - } - unsigned functionIndex() const { return m_functionIndex; @@ -553,7 +593,6 @@ struct SolInterface std::string str() const; - std::string overrideStr() const; /// Returns the Solidity code for all base interfaces /// inherited by this interface. @@ -572,20 +611,12 @@ struct SolInterface void addBases(Interface const& _interface); /// Add functions void addFunctions(Interface const& _interface); - /// Add overrides - void addOverrides(); - /// Helper for adding overrides - void overrideHelper( - std::shared_ptr _function, - std::shared_ptr _interface - ); unsigned m_functionIndex = 0; std::string m_lastBaseName; std::string m_interfaceName; std::vector> m_functions; std::vector> m_baseInterfaces; - std::map, std::vector>> m_overrideMap; std::shared_ptr m_prng; }; diff --git a/test/tools/ossfuzz/protoToSol.cpp b/test/tools/ossfuzz/protoToSol.cpp index 49ee42687..594ebd393 100644 --- a/test/tools/ossfuzz/protoToSol.cpp +++ b/test/tools/ossfuzz/protoToSol.cpp @@ -141,8 +141,7 @@ string ProtoConverter::visit(ContractType const& _contractType) switch (_contractType.contract_type_oneof_case()) { case ContractType::kC: -// return visit(_contractType.c()); - return ""; + return visit(_contractType.c()); case ContractType::kL: return visit(_contractType.l()); case ContractType::kI: @@ -152,9 +151,8 @@ string ProtoConverter::visit(ContractType const& _contractType) } } -string ProtoConverter::visit(Contract const&) +string ProtoConverter::visit(Contract const& _contract) { -#if 0 if (_contract.funcdef_size() == 0 && _contract.bases_size() == 0) return ""; @@ -180,8 +178,6 @@ string ProtoConverter::visit(Contract const&) // Return empty string if input specification is invalid. return ""; } -#endif - return ""; } string ProtoConverter::visit(Interface const& _interface)