From a281173099e4c1634ab6ee709e1d838312aee980 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Sat, 26 Nov 2016 14:10:11 +0100 Subject: [PATCH] Fix for sigsegv stack overflow behavior Also stops Catch from assuming its the only signal user in the binary, and makes it restore the signal handlers it has replaced. Same goes for the signal stack. The signal stack itself probably shouldn't be always reallocated for fragmentation reasons, but that can be fixed later on. --- include/internal/catch_fatal_condition.hpp | 29 ++++++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/include/internal/catch_fatal_condition.hpp b/include/internal/catch_fatal_condition.hpp index dd21d590..e57d8810 100644 --- a/include/internal/catch_fatal_condition.hpp +++ b/include/internal/catch_fatal_condition.hpp @@ -60,22 +60,41 @@ namespace Catch { fatal( "", -sig ); } - FatalConditionHandler() : m_isSet( true ) { - for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) - signal( signalDefs[i].id, handleSignal ); + FatalConditionHandler(): m_isSet(true), m_altStackMem(new char[SIGSTKSZ]) { + stack_t sigStack; + sigStack.ss_sp = m_altStackMem; + sigStack.ss_size = SIGSTKSZ; + sigStack.ss_flags = 0; + sigaltstack(&sigStack, &m_oldSigStack); + struct sigaction sa = { 0 }; + + sa.sa_handler = handleSignal; + sa.sa_flags = SA_ONSTACK; + for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) { + sigaction(signalDefs[i].id, &sa, &m_oldSigActions[i]); + } } ~FatalConditionHandler() { reset(); + delete[] m_altStackMem; } void reset() { if( m_isSet ) { - for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) - signal( signalDefs[i].id, SIG_DFL ); + // Set signals back to previous values -- hopefully nobody overwrote them in the meantime + for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) { + sigaction(signalDefs[i].id, &m_oldSigActions[i], CATCH_NULL); + } + // Return the old stack + sigaltstack(&m_oldSigStack, CATCH_NULL); m_isSet = false; } } bool m_isSet; + // C++03 doesn't allow auto_ptr, so we have manage the memory ourselves + char* m_altStackMem; + struct sigaction m_oldSigActions [sizeof(signalDefs)/sizeof(SignalDefs)]; + stack_t m_oldSigStack; }; } // namespace Catch