mirror of
https://github.com/catchorg/Catch2.git
synced 2024-11-17 11:12:25 +01:00
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.
This commit is contained in:
parent
30cebd6177
commit
e810d9602e
@ -37,6 +37,8 @@ namespace Catch {
|
|||||||
#else // Not Windows - assumed to be POSIX compatible //////////////////////////
|
#else // Not Windows - assumed to be POSIX compatible //////////////////////////
|
||||||
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <memory>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
@ -60,22 +62,39 @@ namespace Catch {
|
|||||||
fatal( "<unknown signal>", -sig );
|
fatal( "<unknown signal>", -sig );
|
||||||
}
|
}
|
||||||
|
|
||||||
FatalConditionHandler() : m_isSet( true ) {
|
FatalConditionHandler(): m_isSet(true), m_altStackMem(new char[SIGSTKSZ]) {
|
||||||
for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i )
|
stack_t sigStack;
|
||||||
signal( signalDefs[i].id, handleSignal );
|
sigStack.ss_sp = m_altStackMem.get();
|
||||||
|
sigStack.ss_size = SIGSTKSZ;
|
||||||
|
sigStack.ss_flags = 0;
|
||||||
|
sigaltstack(&sigStack, &m_oldSigActions);
|
||||||
|
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() {
|
~FatalConditionHandler() {
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
void reset() {
|
void reset() {
|
||||||
if( m_isSet ) {
|
if( m_isSet ) {
|
||||||
for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i )
|
// Set signals back to previous values -- hopefully nobody overwrote them in the meantime
|
||||||
signal( signalDefs[i].id, SIG_DFL );
|
for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) {
|
||||||
|
sigaction(signalDefs[i].id, &m_oldSigActions[i], nullptr);
|
||||||
|
}
|
||||||
|
// Return the old stack
|
||||||
|
sigaltstack(&m_oldSigStack, nullptr);
|
||||||
m_isSet = false;
|
m_isSet = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool m_isSet;
|
bool m_isSet;
|
||||||
|
std::unique_ptr<char[]> m_altStackMem;
|
||||||
|
std::array<struct sigaction, sizeof(signalDefs)/sizeof(SignalDefs)> m_oldSigActions;
|
||||||
|
stack_t m_oldSigStack;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Catch
|
} // namespace Catch
|
||||||
|
Loading…
Reference in New Issue
Block a user