I need to unit test some code where the failure cases raise an exception. In a nutshell, I need to handle the exception by either unwinding a stack frame or making a local jump over the error. Using MSVC is not an option.
The MSDN example for AddVectoredExceptionHandler indicates that I can modify eip and then return EXCEPTION_CONTINUE_EXECUTION to perform a local jump. The obvious question is what to what address to jump. GCC's Label as Value feature seems like it should be just the thing.
The example below works if there is a single return from the erroring function. However, if a second return statement is added, the offset of the jump is suspiciously small and the jump fails. Why?
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0502
#endif
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
static bool handler_called;
static DWORD handler_eip;
static LONG WINAPI local_handler(struct _EXCEPTION_POINTERS* ExceptionInfo) {
handler_called = true;
PCONTEXT Context = ExceptionInfo->ContextRecord;
Context->Eip = handler_eip;
return EXCEPTION_CONTINUE_EXECUTION;
}
static void badcall(void) {
handler_called = false;
handler_eip = &&fail;
int value = 100;
int zero = 0;
value = value/0;
printf("not handled.\n");
assert(false);
//return; // Uncomment this to break the handler
fail:
printf("error handled.\n");
return;
}
int main(int argc, char* argv[]) {
void* old_handler = SetUnhandledExceptionFilter(&local_handler);
badcall();
SetUnhandledExceptionFilter(old_handler);
return(0);
}