KhronosGroup / KhronosGroup/SPIRV-Tools

Stack overflow from `spvtools::opt::SSARewriter::GetReachingDef` recursion

Open
#6,465 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
1.4k
Forks
709
Avg merge
1d 22h
Merged PRs (30d)
28

Description

Achieved on a similar test case to #6104

We're compiling this HLSL shader which we need to compile with `-fcgl` to get to the SPIR-V
https://godbolt.org/z/r75PE1xWM

[The resulting SPIR-V attached](https://github.com/user-attachments/files/24124982/sometimes_crashes.zip)

I don't know how to invoke the `spv-opt` properly on Godbolt with illegal SPIR-V, probably assembler complains before even seeing `--legalize-hlsl`
https://godbolt.org/z/fEMcoKTv3

Results in this callstack before crashing in DXC without the `-fcgl` flag inside of SPIR-V Opt.
```
msvcp140d.dll!00007ff8c692076e() Unknown
msvcp140d.dll!00007ff8c691ea06() Unknown
> dxcompiler.dll!std::_Iterator_base12::_Adopt_locked(const std::_Container_base12 * _Parent) Line 1367 C++
dxcompiler.dll!std::_Iterator_base12::_Adopt(const std::_Container_base12 * _Parent) Line 1307 C++
dxcompiler.dll!std::_List_unchecked_const_iterator,std::equal_to,std::allocator>>>>>,std::_Iterator_base12>::_List_unchecked_const_iterator,std::equal_to,std::allocator>>>>>,std::_Iterator_base12>(std::_List_node,std::equal_to,std::allocator>>>,void *> * _Pnode, const std::_List_val,std::equal_to,std::allocator>>>>> * _Plist) Line 38 C++
dxcompiler.dll!std::_List_const_iterator,std::equal_to,std::allocator>>>>>>::_List_const_iterator,std::equal_to,std::allocator>>>>>>(std::_List_node,std::equal_to,std::allocator>>>,void *> *) C++
dxcompiler.dll!std::_List_iterator,std::equal_to,std::allocator>>>>>>::_List_iterator,std::equal_to,std::allocator>>>>>>(std::_List_node,std::equal_to,std::allocator>>>,void *> *) C++
dxcompiler.dll!std::list,std::equal_to,std::allocator>>>,std::allocator,std::equal_to,std::allocator>>>>>::_Make_iter(std::_List_node,std::equal_to,std::allocator>>>,void *> * _Where) Line 1137 C++
dxcompiler.dll!std::_Hash,std::equal_to,std::allocator>>,std::_Uhash_compare,std::equal_to>,std::allocator,std::equal_to,std::allocator>>>>,0>>::find(spvtools::opt::BasicBlock * const & _Keyval) Line 1231 C++
dxcompiler.dll!spvtools::opt::SSARewriter::GetValueAtBlock(unsigned int var_id, spvtools::opt::BasicBlock * bb) Line 247 C++
dxcompiler.dll!spvtools::opt::SSARewriter::GetReachingDef(unsigned int var_id, spvtools::opt::BasicBlock * bb) Line 260 C++
dxcompiler.dll!spvtools::opt::SSARewriter::GetReachingDef(unsigned int var_id, spvtools::opt::BasicBlock * bb) Line 268 C++
dxcompiler.dll!spvtools::opt::SSARewriter::GetReachingDef(unsigned int var_id, spvtools::opt::BasicBlock * bb) Line 268 C++
dxcompiler.dll!spvtools::opt::SSARewriter::GetReachingDef(unsigned int var_id, spvtools::opt::BasicBlock * bb) Line 268 C++
dxcompiler.dll!spvtools::opt::SSARewriter::GetReachingDef(unsigned int var_id, spvtools::opt::BasicBlock * bb) Line 268 C++
dxcompiler.dll!spvtools::opt::SSARewriter::GetReachingDef(unsigned int var_id, spvtools::opt::BasicBlock * bb) Line 268 C++
dxcompiler.dll!spvtools::opt::SSARewriter::GetReachingDef(unsigned int var_id, spvtools::opt::BasicBlock * bb) Line 268 C++
dxcompiler.dll!spvtools::opt::SSARewriter::GetReachingDef(unsigned int var_id, spvtools::opt::BasicBlock * bb) Line 268 C++
dxcompiler.dll!spvtools::opt::SSARewriter::GetReachingDef(unsigned int var_id, spvtools::opt::BasicBlock * bb) Line 268 C++
dxcompiler.dll!spvtools::opt::SSARewriter::GetReachingDef(unsigned int var_id, spvtools::opt::BasicBlock * bb) Line 268 C++
dxcompiler.dll!spvtools::opt::SSARewriter::GetReachingDef(unsigned int var_id, spvtools::opt::BasicBlock * bb) Line 268 C++
dxcompiler.dll!spvtools::opt::SSARewriter::GetReachingDef(unsigned int var_id, spvtools::opt::BasicBlock * bb) Line 268 C++
dxcompiler.dll!spvtools::opt::SSARewriter::GetReachingDef(unsigned int var_id, spvtools::opt::BasicBlock * bb) Line 268 C++
dxcompiler.dll!spvtools::opt::SSARewriter::GetReachingDef(unsigned int var_id, spvtools::opt::BasicBlock * bb) Line 268 C++
dxcompiler.dll!spvtools::opt::SSARewriter::GetReachingDef(unsigned int var_id, spvtools::opt::BasicBlock * bb) Line 268 C++
dxcompiler.dll!spvtools::opt::SSARewriter::GetReachingDef(unsigned int var_id, spvtools::opt::BasicBlock * bb) Line 268 C++
dxcompiler.dll!spvtools::opt::SSARewriter::GetReachingDef(unsigned int var_id, spvtools::opt::BasicBlock * bb) Line 268 C++
dxcompiler.dll!spvtools::opt::SSARewriter::GetReachingDef(unsigned int var_id, spvtools::opt::BasicBlock * bb) Line 268 C++
dxcompiler.dll!spvtools::opt::SSARewriter::GetReachingDef(unsigned int var_id, spvtools::opt::BasicBlock * bb) Line 268 C++
dxcompiler.dll!spvtools::opt::SSARewriter::GetReachingDef(unsigned int var_id, spvtools::opt::BasicBlock * bb) Line 268 C++
dxcompiler.dll!spvtools::opt::SSARewriter::GetReachingDef(unsigned int var_id, spvtools::opt::BasicBlock * bb) Line 268 C++
dxcompiler.dll!spvtools::opt::SSARewriter::GetReachingDef(unsigned int var_id, spvtools::opt::BasicBlock * bb) Line 268 C++
...
The maximum number of stack frames supported by Visual Studio has been exceeded.

```

Its also possible that the illegal SPIR-V emitted by DXC is causing infinite recursion / loops in the parsed SPIR-V, because the input HLSL is just a simple unit-test shader, so I doubt the chains are so deep to actually overflow the stack which is a few megs.

Contributor guide

Open the contributing guide

Research direction

Start at spvtools::opt::SSARewriter::GetReachingDef and inspect the attached SPIR-V and the HLSL reproducer from the linked Godbolt examples. Determine whether the recursion is caused by illegal SPIR-V or a genuinely deep reaching-definition chain; done means the reproducer no longer overflows the stack.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.