java-topology/defects/solc/patch/solc-0001-callgraph-cyclefinder-uset.patch

52 lines
1.6 KiB
Diff

# UNDF: UNDF-2026-000000288
diff --git a/libyul/optimiser/CallGraphGenerator.cpp b/libyul/optimiser/CallGraphGenerator.cpp
index b8cb7c3..patched 100644
--- a/libyul/optimiser/CallGraphGenerator.cpp
+++ b/libyul/optimiser/CallGraphGenerator.cpp
@@ -28,6 +28,7 @@
#include <libsolutil/CommonData.h>
#include <libsolutil/Visitor.h>
+#include <unordered_set>
#include <stack>
using namespace solidity;
@@ -37,12 +38,16 @@ namespace
{
// TODO: This algorithm is non-optimal.
struct CallGraphCycleFinder
{
CallGraph const& callGraph;
std::set<FunctionHandle> containedInCycle{};
std::set<FunctionHandle> visited{};
std::vector<FunctionHandle> currentPath{};
+ std::set<FunctionHandle> currentPathSet{};
void visit(FunctionHandle const& _function)
{
if (visited.count(_function))
return;
- if (
- auto it = find(currentPath.begin(), currentPath.end(), _function);
- it != currentPath.end()
- )
- containedInCycle.insert(it, currentPath.end());
+ if (currentPathSet.count(_function))
+ {
+ // Function is already in the current DFS path — it is part of a cycle.
+ // Walk currentPath to find where the cycle begins and collect all members.
+ auto it = find(currentPath.begin(), currentPath.end(), _function);
+ containedInCycle.insert(it, currentPath.end());
+ }
else
{
currentPath.emplace_back(_function);
+ currentPathSet.insert(_function);
if (callGraph.functionCalls.count(_function))
for (auto const& child: callGraph.functionCalls.at(_function))
visit(child);
currentPath.pop_back();
+ currentPathSet.erase(_function);
visited.insert(_function);
}
}