You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[BUG] A deeply nested plan overflows the stack before MaxParseDepth can refuse it, ending the process #589
All: the shared parser in PlanViewer.Core (Services/ShowPlanParser.cs)
Performance Studio Version
dev @ 5b7a6c7. Measured against main @ 7a16042, which has the same parser structure.
Operating System
Any. The numbers below are for 1 MB and 1.5 MB thread stacks; 1 MB is the Windows default for a main/UI thread.
Describe the Bug
A legitimately deep plan crashes the process with a stack overflow before MaxParseDepth (1,000) can refuse it. A stack overflow can't be caught in .NET, so the process ends; it doesn't show an error.
Measured in a crash-safe child process against main @ 7a16042, running parse + analyze on the calling thread:
1 MB stack: the process dies at a plan depth of about 450–480 nested operators.
1.5 MB stack: it dies at about 650–750.
MaxParseDepth is 1,000 (ShowPlanParser.cs:19), so the guard is unreachable on a normal caller thread. dev @ 5b7a6c7 has the same shape: the recursive walk runs on whatever thread calls Parse, with no dedicated larger-stack thread.
Plans with hundreds of nested operators are uncommon but real (large reporting queries, deeply nested views). A crafted plan can also get there under the size cap.
Parse walks on a dedicated thread with a 32 MB stack, joined synchronously, so the public signature is unchanged. The 1,000-level guard now fires, and 1,001 levels gives a clean parse error.
An explicit-stack loop replaced one recursive iterator over non-operator children, which even 32 MB didn't cover for crafted input.
A catch-all on that thread, so nothing can go unhandled there.
Pins: parse→analyze→score→layout at depth 150 and 999 on real 1 MB and 1.5 MB threads, and 1,001 refused.
Steps to Reproduce
Generate a showplan whose RelOp nesting is ~500 levels deep (for example, a synthetic plan built programmatically, or a very deep nested-loop / nested-view query plan).
Open or analyze it in Performance Studio (the desktop app or planview analyze).
Expected Behavior
Plans up to MaxParseDepth parse, and deeper ones are refused with a clear parse error. The app keeps running.
Actual Behavior
The process terminates with a stack overflow at around 450–480 levels on a 1 MB stack.
Plan File
A synthetic nested-RelOp plan reproduces it. The generator PerformanceMonitor used for its pins produces one at any depth.
Activity
Review fixes for #589: Query Store MCP parse errors, share errors, tests
Parse deep plans on a large-stack thread (#589)
Merge pull request #591 from erikdarlingdata/fix/589-deep-plan-stack
erikdarlingdata commentedon Sep 28, 2026
Fixed by #591, merged to dev. Ships in the next release.