Skip to content

Conversation

@uenoku
Copy link
Member

@uenoku uenoku commented Oct 16, 2025

This commit addresses a race condition and memory corruption issue in the LongestPathAnalysis where concurrent access to cached results could lead to iterator invalidation and memory corruption. The issue occurred when the cachedResults DenseMap was modified during iteration, causing existing iterators and references to become invalid and point to corrupted memory.

The fix changes the cachedResults map to store unique_ptr<SmallVector> instead of SmallVector directly. This ensures that the underlying SmallVector objects remain at stable memory locations even when the DenseMap is rehashed or modified, preventing iterator invalidation and memory corruption.

Additionally, in markRegEndPoint, we now preemptively call getOrComputePaths for the endpoint before recording paths. This ensures all necessary paths are computed and cached before any operations that might trigger map modifications, eliminating the race condition.

Additional unique_ptr is not ideal so eventually we might want to use BumpAllocator

…ysis caching

This commit addresses a race condition and memory corruption issue in the
LongestPathAnalysis where concurrent access to cached results could lead to
iterator invalidation and memory corruption. The issue occurred when the
cachedResults DenseMap was modified during iteration, causing existing
iterators and references to become invalid and point to corrupted memory.

The fix changes the cachedResults map to store unique_ptr<SmallVector<OpenPath>>
instead of SmallVector<OpenPath> directly. This ensures that the underlying
SmallVector objects remain at stable memory locations even when the DenseMap
is rehashed or modified, preventing iterator invalidation and memory corruption.

Additionally, in markRegEndPoint, we now preemptively call getOrComputePaths
for the endpoint before recording paths. This ensures all necessary paths are
computed and cached before any operations that might trigger map modifications,
eliminating the race condition.

Additional unique_ptr is not ideal so eventually we might want to use BumpAllocator
Copy link
Member

@seldridge seldridge left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice solution. Is there any possibility of parallel insertion into the cachedResults that has to be considered? (Or is that entirely taken care of by the pre-emptive call to getOrComputePath?)

Comment on lines -733 to +734
DenseMap<std::pair<Value, size_t>, SmallVector<OpenPath>> cachedResults;
DenseMap<std::pair<Value, size_t>, std::unique_ptr<SmallVector<OpenPath>>>
cachedResults;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated, consider a struct over std::pair in a follow-on. This has the benefit of readability as well as possibly getting this onto one line. 😉

@uenoku uenoku force-pushed the dev/hidetou/fix-longest-path branch from e5f0bb0 to bfd6106 Compare October 18, 2025 18:34
@uenoku
Copy link
Member Author

uenoku commented Oct 18, 2025

Is there any possibility of parallel insertion into the cachedResults that

cacheResults is intended to cache results under the current module scope and the cache must be frozen if accessed from other threads (which are basically computing paths from parent scope). The issue was that cache was not pre-computed properly in the module scope.

@uenoku uenoku merged commit b597360 into main Oct 18, 2025
7 checks passed
@uenoku uenoku deleted the dev/hidetou/fix-longest-path branch October 18, 2025 18:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants