llvm / llvm/llvm-project

`WinEHPrepare` generates invalid SEH control flow when a multicolor basic block has its BlockAddress taken

Open
#197,908 5 comments 0 reactions 0 assignees View on GitHub
llvm:codegen
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

In LLVM IR, it seems to be valid for a basic block to be reachable from multiple EH funclets. When compiling for Windows SEH, `WinEHPrepare::cloneCommonBlocks` resolves this by cloning the shared block so that each funclet receives its own dedicated copy, maintaining strict SEH boundaries.

However, a problem is if the `BlockAddress` of a multicolor block is taken. Because `BlockAddress` is a global `Constant`, `WinEHPrepare` does not update it during the cloning process. The `BlockAddress` continues to point to the original, un-cloned basic block.

If an `indirectbr` inside a funclet jumps to this `BlockAddress`, control flow will illegally transfer to the original block, which may now be assigned to the parent function or an entirely different funclet. This breaks strict Windows SEH funclet boundaries, resulting in backend crashes or silent SEH corruption at runtime.

**I can do a fix PR later but I have some questions**
1. Was this scenario intentionally omitted because language frontends (like Clang) explicitly forbid computed gotos (`&&label`) from crossing into EH scopes, meaning such IR is essentially never generated by standard frontends?
2. Since `BlockAddress` is a static constant and the target block is duplicated into N copies, there is a fundamental ambiguity regarding which clone the address should point to. Is this the primary reason it hasn't been handled in the backend?
3. I am interested in implementing a fix for this in the EH preparation pipeline. Is there a way to handle this directly without violating any matter like architectural philosophy? For instance:
- Should `WinEHPrepare` intercept and dynamically rewrite `indirectbr` instructions based on the active funclet?
- Should the IR Verifier simply be updated to explicitly reject taking the `BlockAddress` of a block reachable by multiple EH pads?

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.