java-topology/defects/solc/patch/solc-0001-callgraph-cyclefinder-uset.patch
russell@unturf.com 0a580b313d undefect. CWE-407 — 63 sites patched across 27 ecosystems
Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com

Patches, unit tests, benchmarks, whitepaper, and outreach briefs.
Public domain — no copyright claimed. Use freely.
2026-03-26 17:11:57 -04:00

51 lines
1.6 KiB
Diff

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);
}
}