/*** *secfail.c - Report a /GS security check failure * * Copyright (c) 2000-2001, Microsoft Corporation. All rights reserved. * *Purpose: * Define function used to report a security check failure, along with a * routine for registering a new handler. * * Entrypoints: * __security_error_handler * _set_security_error_handler * * NOTE: The ATLMINCRT library includes a version of this file. If any * changes are made here, they should be duplicated in the ATL version. * *Revision History: * 01-24-00 PML Created. * 08-09-00 PML Never return from failure reporting. * 08-29-00 PML Rename handlers, add extra parameters * 03-28-01 PML Protect against GetModuleFileName overflow (vs7#231284) * *******************************************************************************/ #include #include #include #include #include #include /* * User-registered failure reporting routine. */ static _secerr_handler_func user_handler; /* * Default messagebox string components */ #define PROGINTRO "Program: " #define DOTDOTDOT "..." #define BOXINTRO_0 "Unknown security failure detected!" #define MSGTEXT_0 \ "A security error of unknown cause has been detected which has\n" \ "corrupted the program's internal state. The program cannot safely\n" \ "continue execution and must now be terminated.\n" #define BOXINTRO_1 "Buffer overrun detected!" #define MSGTEXT_1 \ "A buffer overrun has been detected which has corrupted the program's\n" \ "internal state. The program cannot safely continue execution and must\n"\ "now be terminated.\n" #define MAXLINELEN 60 /* max length for line in message box */ /*** *__security_error_handler() - Report security error. * *Purpose: * A /GS security error has been detected. If a user-registered failure * reporting function is available, call it, otherwise bring up a default * message box describing the problem and terminate the program. * *Entry: * int code - security failure code * void *data - code-specific data * *Exit: * Does not return. * *Exceptions: * *******************************************************************************/ void __cdecl __security_error_handler( int code, void *data) { /* Use user-registered handler if available. */ if (user_handler != NULL) { __try { user_handler(code, data); } __except (EXCEPTION_EXECUTE_HANDLER) { /* * If user handler raises an exception, capture it and terminate * the program, since the EH stack may be corrupted above this * point. */ } } else { char progname[MAX_PATH + 1]; char * pch; char * outmsg; char * boxintro; char * msgtext; size_t subtextlen; switch (code) { default: /* * Unknown failure code, which probably means an older CRT DLL is * being used with a newer compiler. */ boxintro = BOXINTRO_0; msgtext = MSGTEXT_0; subtextlen = sizeof(BOXINTRO_0) + sizeof(MSGTEXT_0); break; case _SECERR_BUFFER_OVERRUN: /* * Buffer overrun detected which may have overwritten a return * address. */ boxintro = BOXINTRO_1; msgtext = MSGTEXT_1; subtextlen = sizeof(BOXINTRO_1) + sizeof(MSGTEXT_1); break; } /* * In debug CRT, report error with ability to call the debugger. */ _RPT0(_CRT_ERROR, msgtext); progname[MAX_PATH] = '\0'; if (!GetModuleFileName(NULL, progname, MAX_PATH)) strcpy(progname, ""); pch = progname; /* sizeof(PROGINTRO) includes the NULL terminator */ if (sizeof(PROGINTRO) + strlen(progname) + 1 > MAXLINELEN) { pch += (sizeof(PROGINTRO) + strlen(progname) + 1) - MAXLINELEN; strncpy(pch, DOTDOTDOT, sizeof(DOTDOTDOT) - 1); } outmsg = (char *)_alloca(subtextlen - 1 + 2 + sizeof(PROGINTRO) - 1 + strlen(pch) + 2); strcpy(outmsg, boxintro); strcat(outmsg, "\n\n"); strcat(outmsg, PROGINTRO); strcat(outmsg, pch); strcat(outmsg, "\n\n"); strcat(outmsg, msgtext); __crtMessageBoxA( outmsg, "Microsoft Visual C++ Runtime Library", MB_OK|MB_ICONHAND|MB_SETFOREGROUND|MB_TASKMODAL); } _exit(3); } /*** *_set_security_error_handler(handler) - Register user handler * *Purpose: * Register a user failure reporting function. * *Entry: * _secerr_handler_func handler - the user handler * *Exit: * Returns the previous user handler * *Exceptions: * *******************************************************************************/ _secerr_handler_func __cdecl _set_security_error_handler( _secerr_handler_func handler) { _secerr_handler_func old_handler; old_handler = user_handler; user_handler = handler; return old_handler; } /* TEMPORARY - old handler name, to be removed when tools are updated. */ void __cdecl __buffer_overrun() { __security_error_handler(_SECERR_BUFFER_OVERRUN, NULL); } /* TEMPORARY - old handler name, to be removed when tools are updated. */ _secerr_handler_func __cdecl __set_buffer_overrun_handler( _secerr_handler_func handler) { return _set_security_error_handler(handler); }