Every time I run my code with address and undefined behaviour sanitisers. I get a crash in random places usually in Spirv-Cross and it doesn't go further. An example of this is below. It has taken me a a while to work this out as this is working fine in normal conditions. The reason is there is a stack-overflow happening in SPIRV-Cross's recursive MSL codegen on worker threads only. ChatGPT says.
I tested this theory, below is a reproducer and steps to build and run in parallel vs non-parallel modes. This happens in one of my shaders test.frag with a ridiculously long nested if/else if statements.
I guess it's probably too much to ask to remove recursions, however this means in some cases sanitisers can't be used because of this. The demo will run on linux but I can't reproduce the issue. It's MacOs specific.
AddressSanitizer:DEADLYSIGNAL
AddressSanitizer=================================================================
:DEADLYSIGNAL
==25550==ERROR: AddressSanitizer: stack-overflow on address 0x00016fa73de0 (pc 0x00010538b2b4 bp 0x00016fa74660 sp 0x00016fa73da0 T1)
#0 0x00010538b2b4 in printf_common(void*, char const*, char*)+0xfc (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x1b2b4)
#1 0x00010538bebc in vsprintf+0x64 (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x1bebc)
#2 0x00010538c6f4 in sprintf+0x38 (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x1c6f4)
#3 0x0001020fe980 in spirv_cross::convert_to_string(float, char) spirv_common.hpp:284
#4 0x000101ec1dd4 in spirv_cross::CompilerGLSL::format_float(float) const spirv_glsl.cpp:20235
#5 0x000101ec4dc0 in spirv_cross::CompilerGLSL::convert_float_to_string(spirv_cross::SPIRConstant const&, unsigned int, unsigned int) spirv_glsl.cpp:6383
#6 0x000101ecbffc in spirv_cross::CompilerGLSL::constant_expression_vector(spirv_cross::SPIRConstant const&, unsigned int) spirv_glsl.cpp:6607
#7 0x000101e3e8c8 in spirv_cross::CompilerGLSL::constant_expression(spirv_cross::SPIRConstant const&, bool, bool) spirv_glsl.cpp:6209
#8 0x000101e67c90 in spirv_cross::CompilerGLSL::to_expression(unsigned int, bool) spirv_glsl.cpp:5641
#9 0x000101e8ac3c in spirv_cross::CompilerGLSL::to_unpacked_expression(unsigned int, bool) spirv_glsl.cpp:5348
#10 0x000101e92324 in spirv_cross::CompilerGLSL::to_enclosed_unpacked_expression(unsigned int, bool) spirv_glsl.cpp:5353
#11 0x000101ee13d4 in spirv_cross::CompilerGLSL::emit_binary_op(unsigned int, unsigned int, unsigned int, unsigned int, char const*) spirv_glsl.cpp:7093
#12 0x000101fc413c in spirv_cross::CompilerGLSL::emit_instruction(spirv_cross::Instruction const&) spirv_glsl.cpp:13640
#13 0x00010061eac8 in spirv_cross::CompilerMSL::emit_instruction(spirv_cross::Instruction const&) spirv_msl.cpp:10700
#14 0x000101f7a6f0 in spirv_cross::CompilerGLSL::emit_block_instructions(spirv_cross::SPIRBlock&) spirv_glsl.cpp:12190
#15 0x0001020cf568 in spirv_cross::CompilerGLSL::emit_block_chain_inner(spirv_cross::SPIRBlock&) spirv_glsl.cpp:18426
#16 0x0001020b3548 in spirv_cross::CompilerGLSL::emit_block_chain(spirv_cross::SPIRBlock&) spirv_glsl.cpp:18267
#17 0x0001020b9bb4 in spirv_cross::CompilerGLSL::branch(spirv_cross::TypedID<(spirv_cross::Types)6>, spirv_cross::TypedID<(spirv_cross::Types)6>) spirv_glsl.cpp:17811
#18 0x0001020bb99c in spirv_cross::CompilerGLSL::branch(spirv_cross::TypedID<(spirv_cross::Types)6>, unsigned int, spirv_cross::TypedID<(spirv_cross::Types)6>, spirv_cross::TypedID<(spirv_cross::Types)6>) spirv_glsl.cpp:17840
#19 0x0001020d161c in spirv_cross::CompilerGLSL::emit_block_chain_inner(spirv_cross::SPIRBlock&) spirv_glsl.cpp:18497
#20 0x0001020b3548 in spirv_cross::CompilerGLSL::emit_block_chain(spirv_cross::SPIRBlock&) spirv_glsl.cpp:18267
#21 0x0001020b9bb4 in spirv_cross::CompilerGLSL::branch(spirv_cross::TypedID<(spirv_cross::Types)6>, spirv_cross::TypedID<(spirv_cross::Types)6>) spirv_glsl.cpp:17811
#22 0x0001020bbb8c in spirv_cross::CompilerGLSL::branch(spirv_cross::TypedID<(spirv_cross::Types)6>, unsigned int, spirv_cross::TypedID<(spirv_cross::Types)6>, spirv_cross::TypedID<(spirv_cross::Types)6>) spirv_glsl.cpp:17847
#23 0x0001020d161c in spirv_cross::CompilerGLSL::emit_block_chain_inner(spirv_cross::SPIRBlock&) spirv_glsl.cpp:18497
#24 0x0001020b3548 in spirv_cross::CompilerGLSL::emit_block_chain(spirv_cross::SPIRBlock&) spirv_glsl.cpp:18267
#25 0x0001020b9bb4 in spirv_cross::CompilerGLSL::branch(spirv_cross::TypedID<(spirv_cross::Types)6>, spirv_cross::TypedID<(spirv_cross::Types)6>) spirv_glsl.cpp:17811
#26 0x0001020bbb8c in spirv_cross::CompilerGLSL::branch(spirv_cross::TypedID<(spirv_cross::Types)6>, unsigned int, spirv_cross::TypedID<(spirv_cross::Types)6>, spirv_cross::TypedID<(spirv_cross::Types)6>) spirv_glsl.cpp:17847
#27 0x0001020d161c in spirv_cross::CompilerGLSL::emit_block_chain_inner(spirv_cross::SPIRBlock&) spirv_glsl.cpp:18497
#28 0x0001020b3548 in spirv_cross::CompilerGLSL::emit_block_chain(spirv_cross::SPIRBlock&) spirv_glsl.cpp:18267
#29 0x0001020b9bb4 in spirv_cross::CompilerGLSL::branch(spirv_cross::TypedID<(spirv_cross::Types)6>, spirv_cross::TypedID<(spirv_cross::Types)6>) spirv_glsl.cpp:17811
#30 0x0001020bbb8c in spirv_cross::CompilerGLSL::branch(spirv_cross::TypedID<(spirv_cross::Types)6>, unsigned int, spirv_cross::TypedID<(spirv_cross::Types)6>, spirv_cross::TypedID<(spirv_cross::Types)6>) spirv_glsl.cpp:17847
#31 0x0001020d161c in spirv_cross::CompilerGLSL::emit_block_chain_inner(spirv_cross::SPIRBlock&) spirv_glsl.cpp:18497
#32 0x0001020b3548 in spirv_cross::CompilerGLSL::emit_block_chain(spirv_cross::SPIRBlock&) spirv_glsl.cpp:18267
#33 0x0001020b9bb4 in spirv_cross::CompilerGLSL::branch(spirv_cross::TypedID<(spirv_cross::Types)6>, spirv_cross::TypedID<(spirv_cross::Types)6>) spirv_glsl.cpp:17811
#34 0x0001020bbb8c in spirv_cross::CompilerGLSL::branch(spirv_cross::TypedID<(spirv_cross::Types)6>, unsigned int, spirv_cross::TypedID<(spirv_cross::Types)6>, spirv_cross::TypedID<(spirv_cross::Types)6>) spirv_glsl.cpp:17847
#35 0x0001020d161c in spirv_cross::CompilerGLSL::emit_block_chain_inner(spirv_cross::SPIRBlock&) spirv_glsl.cpp:18497
#36 0x0001020b3548 in spirv_cross::CompilerGLSL::emit_block_chain(spirv_cross::SPIRBlock&) spirv_glsl.cpp:18267
#37 0x0001020b9bb4 in spirv_cross::CompilerGLSL::branch(spirv_cross::TypedID<(spirv_cross::Types)6>, spirv_cross::TypedID<(spirv_cross::Types)6>) spirv_glsl.cpp:17811
#38 0x0001020bbb8c in spirv_cross::CompilerGLSL::branch(spirv_cross::TypedID<(spirv_cross::Types)6>, unsigned int, spirv_cross::TypedID<(spirv_cross::Types)6>, spirv_cross::TypedID<(spirv_cross::Types)6>) spirv_glsl.cpp:17847
#39 0x0001020d161c in spirv_cross::CompilerGLSL::emit_block_chain_inner(spirv_cross::SPIRBlock&) spirv_glsl.cpp:18497
#40 0x0001020b3548 in spirv_cross::CompilerGLSL::emit_block_chain(spirv_cross::SPIRBlock&) spirv_glsl.cpp:18267
#41 0x0001020b9bb4 in spirv_cross::CompilerGLSL::branch(spirv_cross::TypedID<(spirv_cross::Types)6>, spirv_cross::TypedID<(spirv_cross::Types)6>) spirv_glsl.cpp:17811
#42 0x0001020bbb8c in spirv_cross::CompilerGLSL::branch(spirv_cross::TypedID<(spirv_cross::Types)6>, unsigned int, spirv_cross::TypedID<(spirv_cross::Types)6>, spirv_cross::TypedID<(spirv_cross::Types)6>) spirv_glsl.cpp:17847
#43 0x0001020d161c in spirv_cross::CompilerGLSL::emit_block_chain_inner(spirv_cross::SPIRBlock&) spirv_glsl.cpp:18497
#44 0x0001020b3548 in spirv_cross::CompilerGLSL::emit_block_chain(spirv_cross::SPIRBlock&) spirv_glsl.cpp:18267
#45 0x0001020b9bb4 in spirv_cross::CompilerGLSL::branch(spirv_cross::TypedID<(spirv_cross::Types)6>, spirv_cross::TypedID<(spirv_cross::Types)6>) spirv_glsl.cpp:17811
#46 0x0001020bbb8c in spirv_cross::CompilerGLSL::branch(spirv_cross::TypedID<(spirv_cross::Types)6>, unsigned int, spirv_cross::TypedID<(spirv_cross::Types)6>, spirv_cross::TypedID<(spirv_cross::Types)6>) spirv_glsl.cpp:17847
#47 0x0001020d161c in spirv_cross::CompilerGLSL::emit_block_chain_inner(spirv_cross::SPIRBlock&) spirv_glsl.cpp:18497
#48 0x0001020b3548 in spirv_cross::CompilerGLSL::emit_block_chain(spirv_cross::SPIRBlock&) spirv_glsl.cpp:18267
#49 0x0001020b9bb4 in spirv_cross::CompilerGLSL::branch(spirv_cross::TypedID<(spirv_cross::Types)6>, spirv_cross::TypedID<(spirv_cross::Types)6>) spirv_glsl.cpp:17811
#50 0x0001020bbb8c in spirv_cross::CompilerGLSL::branch(spirv_cross::TypedID<(spirv_cross::Types)6>, unsigned int, spirv_cross::TypedID<(spirv_cross::Types)6>, spirv_cross::TypedID<(spirv_cross::Types)6>) spirv_glsl.cpp:17847
#51 0x0001020d161c in spirv_cross::CompilerGLSL::emit_block_chain_inner(spirv_cross::SPIRBlock&) spirv_glsl.cpp:18497
#52 0x0001020b3548 in spirv_cross::CompilerGLSL::emit_block_chain(spirv_cross::SPIRBlock&) spirv_glsl.cpp:18267
#53 0x0001020b9bb4 in spirv_cross::CompilerGLSL::branch(spirv_cross::TypedID<(spirv_cross::Types)6>, spirv_cross::TypedID<(spirv_cross::Types)6>) spirv_glsl.cpp:17811
#54 0x0001020bbb8c in spirv_cross::CompilerGLSL::branch(spirv_cross::TypedID<(spirv_cross::Types)6>, unsigned int, spirv_cross::TypedID<(spirv_cross::Types)6>, spirv_cross::TypedID<(spirv_cross::Types)6>) spirv_glsl.cpp:17847
#55 0x0001020d161c in spirv_cross::CompilerGLSL::emit_block_chain_inner(spirv_cross::SPIRBlock&) spirv_glsl.cpp:18497
#56 0x0001020b3548 in spirv_cross::CompilerGLSL::emit_block_chain(spirv_cross::SPIRBlock&) spirv_glsl.cpp:18267
#57 0x0001020b9bb4 in spirv_cross::CompilerGLSL::branch(spirv_cross::TypedID<(spirv_cross::Types)6>, spirv_cross::TypedID<(spirv_cross::Types)6>) spirv_glsl.cpp:17811
#58 0x0001020bbb8c in spirv_cross::CompilerGLSL::branch(spirv_cross::TypedID<(spirv_cross::Types)6>, unsigned int, spirv_cross::TypedID<(spirv_cross::Types)6>, spirv_cross::TypedID<(spirv_cross::Types)6>) spirv_glsl.cpp:17847
#59 0x0001020d161c in spirv_cross::CompilerGLSL::emit_block_chain_inner(spirv_cross::SPIRBlock&) spirv_glsl.cpp:18497
#60 0x0001020b36b4 in spirv_cross::CompilerGLSL::emit_block_chain(spirv_cross::SPIRBlock&) spirv_glsl.cpp:18272
#61 0x000101ddbbbc in spirv_cross::CompilerGLSL::emit_function(spirv_cross::SPIRFunction&, spirv_cross::Bitset const&) spirv_glsl.cpp:17585
#62 0x000101dd838c in spirv_cross::CompilerGLSL::emit_function(spirv_cross::SPIRFunction&, spirv_cross::Bitset const&) spirv_glsl.cpp:17465
#63 0x0001004328b4 in spirv_cross::CompilerMSL::compile() spirv_msl.cpp:1851
#64 0x0001003aa2cc in (anonymous namespace)::compile_spirv_to_msl(std::__1::vector<unsigned int, std::__1::allocator<unsigned int>> const&) spv_test.cpp:153
#65 0x0001003a9514 in main::$_0::operator()(unsigned long) const spv_test.cpp:251
#66 0x0001003a927c in void (anonymous namespace)::JobSystem::run<main::$_0 const&>(main::$_0 const&) const::'lambda'()::operator()() const spv_test.cpp:177
#67 0x0001003a90bc in decltype(std::declval<main::$_0 const&>()()) std::__1::__invoke[abi:ne200100]<void (anonymous namespace)::JobSystem::run<main::$_0 const&>(main::$_0 const&) const::'lambda'()>(main::$_0 const&) invoke.h:179
#68 0x0001003a8fb4 in void std::__1::__thread_execute[abi:ne200100]<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, void (anonymous namespace)::JobSystem::run<main::$_0 const&>(main::$_0 const&) const::'lambda'()>(std::__1::tuple<main::$_0 const&, void (anonymous namespace)::JobSystem::run<main::$_0 const&>(main::$_0 const&) const::'lambda'()>&, std::__1::__tuple_indices<>) thread.h:205
#69 0x0001003a81e4 in void* std::__1::__thread_proxy[abi:ne200100]<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, void (anonymous namespace)::JobSystem::run<main::$_0 const&>(main::$_0 const&) const::'lambda'()>>(void*) thread.h:214
#70 0x0001053aa418 in asan_thread_start(void*)+0x4c (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x3a418)
#71 0x00018e1ffc04 in _pthread_start+0x84 (libsystem_pthread.dylib:arm64e+0x6c04)
#72 0x00018e1faba4 in thread_start+0x4 (libsystem_pthread.dylib:arm64e+0x1ba4)
SUMMARY: AddressSanitizer: stack-overflow spirv_common.hpp:284 in spirv_cross::convert_to_string(float, char)
Thread T1 created by T0 here:
#0 0x0001053a59f8 in pthread_create+0x5c (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x359f8)
#1 0x0001003a7fac in std::__1::__libcpp_thread_create[abi:ne200100](_opaque_pthread_t**, void* (*)(void*), void*) pthread.h:182
#2 0x0001003a7c24 in std::__1::thread::thread<void (anonymous namespace)::JobSystem::run<main::$_0 const&>(main::$_0 const&) const::'lambda'(), 0>(main::$_0 const&) thread.h:224
#3 0x0001003a7984 in std::__1::thread::thread<void (anonymous namespace)::JobSystem::run<main::$_0 const&>(main::$_0 const&) const::'lambda'(), 0>(main::$_0 const&) thread.h:219
#4 0x0001003a7920 in main::$_0 const&* std::__1::construct_at[abi:ne200100]<std::__1::thread, void (anonymous namespace)::JobSystem::run<main::$_0 const&>(main::$_0 const&) const::'lambda'(), std::__1::thread*>(main::$_0 const&*, void (anonymous namespace)::JobSystem::run<main::$_0 const&>(main::$_0 const&) const::'lambda'()&&) construct_at.h:40
#5 0x0001003a788c in main::$_0 const&* std::__1::__construct_at[abi:ne200100]<std::__1::thread, void (anonymous namespace)::JobSystem::run<main::$_0 const&>(main::$_0 const&) const::'lambda'(), std::__1::thread*>(main::$_0 const&*, void (anonymous namespace)::JobSystem::run<main::$_0 const&>(main::$_0 const&) const::'lambda'()&&) construct_at.h:48
#6 0x0001003a71fc in void std::__1::allocator_traits<std::__1::allocator<std::__1::thread>>::construct[abi:ne200100]<std::__1::thread, void (anonymous namespace)::JobSystem::run<main::$_0 const&>(main::$_0 const&) const::'lambda'(), void, 0>(std::__1::allocator<std::__1::thread>&, main::$_0 const&*, void (anonymous namespace)::JobSystem::run<main::$_0 const&>(main::$_0 const&) const::'lambda'()&&) allocator_traits.h:318
#7 0x0001003a6a78 in void std::__1::vector<std::__1::thread, std::__1::allocator<std::__1::thread>>::__construct_one_at_end[abi:ne200100]<void (anonymous namespace)::JobSystem::run<main::$_0 const&>(main::$_0 const&) const::'lambda'()>(void (anonymous namespace)::JobSystem::run<main::$_0 const&>(main::$_0 const&) const::'lambda'()&&) vector.h:742
#8 0x0001003a192c in std::__1::thread& std::__1::vector<std::__1::thread, std::__1::allocator<std::__1::thread>>::emplace_back<void (anonymous namespace)::JobSystem::run<main::$_0 const&>(main::$_0 const&) const::'lambda'()>(void (anonymous namespace)::JobSystem::run<main::$_0 const&>(main::$_0 const&) const::'lambda'()&&) vector.h:1133
#9 0x00010039515c in void (anonymous namespace)::JobSystem::run<main::$_0 const&>(main::$_0 const&) const spv_test.cpp:177
#10 0x000100392400 in main spv_test.cpp:268
#11 0x00018de35d50 (<unknown module>)
==25550==ABORTING
Every time I run my code with address and undefined behaviour sanitisers. I get a crash in random places usually in Spirv-Cross and it doesn't go further. An example of this is below. It has taken me a a while to work this out as this is working fine in normal conditions. The reason is there is a stack-overflow happening in SPIRV-Cross's recursive MSL codegen on worker threads only. ChatGPT says.
I tested this theory, below is a reproducer and steps to build and run in parallel vs non-parallel modes. This happens in one of my shaders
test.fragwith a ridiculously long nestedif/else ifstatements.I guess it's probably too much to ask to remove recursions, however this means in some cases sanitisers can't be used because of this. The demo will run on linux but I can't reproduce the issue. It's MacOs specific.
Reproducer is
https://github.com/abbaswasim/spv_testgit clone with submodules and then:Run in serial, works fine:
./build.sh -p falseRun in parallel, results in SO:
./build.sh -p trueThere is also an
spv_test_pthreads.cppthat you can see to understand how using pthreads and increasing the stack size helps.