Introduction
Stack corruptions are usually tricky to solve, they can be random or consistent in nature, random are usually due to some rogue pointer writing to a random location wrecking havoc along the process address space and the consistent are due to overrunning allocated write buffer with more bytes that it can hold. The trick I would like to show aims at copping with this second, easier type of memory corruption and this will work only for the cases when the overflown space holder was on the stack
Details
So in the example bellow resetBuff is given a pointer to a 20-byte buffer while asked to memset 100 bytes. Since the pointer is to a local variable (allocated on the stack) and since stack addresses are decreasing this will corrupt data in previous stack frames, for example the test variable. My way to solver it is to offload the offending code to a separate thread and then join it for completion. This way the corruption will happen in a transient stack while our stack will stay intact. As a precaution we may also add a huge dummy buffer in the transient stack to try and keep the corruption from spieling over the transient stack. P.S We cam also simplify this and simply to introduce a padding buffer in the corrupted function (where we hit the SIGSEV) but we are not sure about the order the compiler keeps the local variables on the stack and hence our buffer might get allocated before the corrupted real variable on the stack hence doing no good.
Code:
void resetBuff(char* buff,int len)
{
memset(buff,0,len);
}
void oops()
{
char buff[20];
const int test = 100;
resetBuff(buff,100);
assert(test == 100);
}
************************************
void oopsWorkAround()
{
char buff[20];
const int test = 100;
boost::thread t(&resetBuffbuff,buff,100);
t.join();
assert(test == 100);
}
*************************************
void SafetyWrapper(char* buff,int len)
{
char safetyBuff[1000];
resetBuff(buff,len)
}
void oopsWorkAroundWithSafetyPadding()
{
char buff[20];
const int test = 100;
boost::thread t(&SafetyWrapper,buff,100);
t.join();
assert(test == 100);
}
...