| 64 | } |
| 65 | |
| 66 | CallGraph FunctionCallGraphBuilder::buildDeployedGraph( |
| 67 | ContractDefinition const& _contract, |
| 68 | CallGraph const& _creationGraph |
| 69 | ) |
| 70 | { |
| 71 | FunctionCallGraphBuilder builder(_contract); |
| 72 | solAssert(builder.m_currentNode == CallGraph::Node(CallGraph::SpecialNode::Entry), ""); |
| 73 | |
| 74 | auto getSecondElement = [](auto const& _tuple){ return std::get<1>(_tuple); }; |
| 75 | |
| 76 | // Create graph for all publicly reachable functions |
| 77 | for (FunctionTypePointer functionType: _contract.interfaceFunctionList() | ranges::views::transform(getSecondElement)) |
| 78 | { |
| 79 | auto const* function = dynamic_cast<FunctionDefinition const*>(&functionType->declaration()); |
| 80 | auto const* variable = dynamic_cast<VariableDeclaration const*>(&functionType->declaration()); |
| 81 | |
| 82 | if (function) |
| 83 | builder.functionReferenced(*function); |
| 84 | else |
| 85 | // If it's not a function, it must be a getter of a public variable; we ignore those |
| 86 | solAssert(variable, ""); |
| 87 | } |
| 88 | |
| 89 | if (_contract.fallbackFunction()) |
| 90 | builder.functionReferenced(*_contract.fallbackFunction()); |
| 91 | |
| 92 | if (_contract.receiveFunction()) |
| 93 | builder.functionReferenced(*_contract.receiveFunction()); |
| 94 | |
| 95 | // All functions present in internal dispatch at creation time could potentially be pointers |
| 96 | // assigned to state variables and as such may be reachable after deployment as well. |
| 97 | builder.m_currentNode = CallGraph::SpecialNode::InternalDispatch; |
| 98 | std::set<CallGraph::Node, CallGraph::CompareByID> defaultNode; |
| 99 | for (CallGraph::Node const& dispatchTarget: util::valueOrDefault(_creationGraph.edges, CallGraph::SpecialNode::InternalDispatch, defaultNode)) |
| 100 | { |
| 101 | solAssert(!std::holds_alternative<CallGraph::SpecialNode>(dispatchTarget), ""); |
| 102 | solAssert(std::get<CallableDeclaration const*>(dispatchTarget) != nullptr, ""); |
| 103 | |
| 104 | // Visit the callable to add not only it but also everything it calls too |
| 105 | builder.functionReferenced(*std::get<CallableDeclaration const*>(dispatchTarget), false); |
| 106 | } |
| 107 | |
| 108 | builder.m_currentNode = CallGraph::SpecialNode::Entry; |
| 109 | builder.processQueue(); |
| 110 | |
| 111 | return std::move(builder.m_graph); |
| 112 | } |
| 113 | |
| 114 | bool FunctionCallGraphBuilder::visit(FunctionCall const& _functionCall) |
| 115 | { |
nothing calls this directly
no test coverage detected