Fix CFA stack overflow crash in for loops where initializer throws#4274
Fix CFA stack overflow crash in for loops where initializer throws#4274ibesuperv wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds a regression test for a control-flow analysis stack overflow involving for-loop initializers that always throw inside try/catch, and updates the Go binder to avoid creating an unreachable-cycle in the loop flow graph.
Changes:
- Added a new compiler test case and reference baselines for the repro from TypeScript issue #63092.
- Updated
bindForStatementto bind the initializer before constructing the loop flow graph and to bail out early if the initializer makes flow unreachable.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| testdata/tests/cases/compiler/forLoopInitializerAlwaysThrowsInTryCatch.ts | New regression test covering throwing for initializers in try/catch. |
| testdata/baselines/reference/compiler/forLoopInitializerAlwaysThrowsInTryCatch.types | Baseline types output for the new regression test. |
| testdata/baselines/reference/compiler/forLoopInitializerAlwaysThrowsInTryCatch.symbols | Baseline symbols output for the new regression test. |
| internal/binder/binder.go | Binder change to prevent unreachable-cycle stack overflow during reachability analysis. |
|
@microsoft-github-policy-service agree |
RyanCavanaugh
left a comment
There was a problem hiding this comment.
The copilot review comments seem plausible to me - can you add testcases to verify, and fix if needed?
Hi Ryan! Thank you so much for helping me out with my first PR and guiding me to the right repository. I actually addressed both of Copilot's review comments in the latest force-pushed commit (
|
Fixes microsoft/TypeScript#63092
Analysis
Unlike
whileordo-while, afor-loop's initializer is bound before the loop's flow graph is constructed. If the initializer makes the control flow unreachable (e.g. an IIFE with athrow),addAntecedentfilters out the unreachable entry topreLoopLabel, leaving only the back-edge from the incrementor. This creates a cycle with no exit that causesisReachableFlowNodeWorkerto loop infinitely and overflow the stack.Fix
Bail out early in
bindForStatementif the initializer makes the control flow unreachable, and bind the remaining children as unreachable without constructing the cyclic loop flow graph.Checklist
npx hereby formatnpx hereby lintNote
This PR was developed with AI assistance (Gemini).