diff --git a/cli/cppcheckexecutor.cpp b/cli/cppcheckexecutor.cpp index 8d2a3e8c2..c2cec0940 100644 --- a/cli/cppcheckexecutor.cpp +++ b/cli/cppcheckexecutor.cpp @@ -211,8 +211,9 @@ std::size_t GetArrayLength(const T(&)[size]) #if defined(USE_UNIX_SIGNAL_HANDLING) /* * Try to print the callstack. - * That is very sensitive to the operating system, hardware, compiler and runtime! - * The code is not meant for production environment, it's using functions not whitelisted for usage in a signal handler function. + * That is very sensitive to the operating system, hardware, compiler and runtime. + * The code is not meant for production environment! + * One reason is named first: it's using functions not whitelisted for usage in a signal handler function. */ static void print_stacktrace(FILE* output, bool demangling, int maxdepth, bool lowMem) { @@ -220,8 +221,8 @@ static void print_stacktrace(FILE* output, bool demangling, int maxdepth, bool l // 32 vs. 64bit #define ADDRESSDISPLAYLENGTH ((sizeof(long)==8)?12:8) const int fd = fileno(output); - void *array[32]= {0}; // the less resources the better... - const int currentdepth = backtrace(array, (int)GetArrayLength(array)); + void *callstackArray[32]= {0}; // the less resources the better... + const int currentdepth = backtrace(callstackArray, (int)GetArrayLength(callstackArray)); const int offset=2; // some entries on top are within our own exception handling code or libc if (maxdepth<0) maxdepth=currentdepth-offset; @@ -229,17 +230,16 @@ static void print_stacktrace(FILE* output, bool demangling, int maxdepth, bool l maxdepth = std::min(maxdepth, currentdepth); if (lowMem) { fputs("Callstack (symbols only):\n", output); - backtrace_symbols_fd(array+offset, maxdepth, fd); - fflush(output); + backtrace_symbols_fd(callstackArray+offset, maxdepth, fd); } else { - char **symbolstrings = backtrace_symbols(array, currentdepth); - if (symbolstrings) { + char **symbolStringList = backtrace_symbols(callstackArray, currentdepth); + if (symbolStringList) { fputs("Callstack:\n", output); for (int i = offset; i < maxdepth; ++i) { - const char * const symbol = symbolstrings[i]; - char * realname = nullptr; - const char * const firstBracketName = strchr(symbol, '('); - const char * const firstBracketAddress = strchr(symbol, '['); + const char * const symbolString = symbolStringList[i]; + char * realnameString = nullptr; + const char * const firstBracketName = strchr(symbolString, '('); + const char * const firstBracketAddress = strchr(symbolString, '['); const char * const secondBracketAddress = strchr(firstBracketAddress, ']'); const char * const beginAddress = firstBracketAddress+3; const int addressLen = int(secondBracketAddress-beginAddress); @@ -247,12 +247,14 @@ static void print_stacktrace(FILE* output, bool demangling, int maxdepth, bool l if (demangling && firstBracketName) { const char * const plus = strchr(firstBracketName, '+'); if (plus && (plus>(firstBracketName+1))) { - char input_buffer[512]= {0}; + char input_buffer[1024]= {0}; strncpy(input_buffer, firstBracketName+1, plus-firstBracketName-1); - char output_buffer[1024]= {0}; + char output_buffer[2048]= {0}; size_t length = GetArrayLength(output_buffer); int status=0; - realname = abi::__cxa_demangle(input_buffer, output_buffer, &length, &status); // non-NULL on success + // We're violating the specification - passing stack address instead of malloc'ed heap. + // Benefit is that no further heap is required, while there is sufficient stack... + realnameString = abi::__cxa_demangle(input_buffer, output_buffer, &length, &status); // non-NULL on success } } const int ordinal=i-offset; @@ -261,17 +263,17 @@ static void print_stacktrace(FILE* output, bool demangling, int maxdepth, bool l if (padLen>0) fprintf(output, "%0*d", padLen, 0); - if (realname) { + if (realnameString) { fprintf(output, "%.*s in %s\n", (int)(secondBracketAddress-firstBracketAddress-3), firstBracketAddress+3, - realname); + realnameString); } else { fprintf(output, "%.*s in %.*s\n", (int)(secondBracketAddress-firstBracketAddress-3), firstBracketAddress+3, - (int)(firstBracketAddress-symbol), symbol); + (int)(firstBracketAddress-symbolString), symbolString); } } - free(symbolstrings); + free(symbolStringList); } else { fputs("Callstack could not be obtained\n", output); } @@ -319,7 +321,7 @@ static const Signalmap_t listofsignals = make_container< Signalmap_t > () DECLARE_SIGNAL(SIGSYS) // don't care: SIGTERM DECLARE_SIGNAL(SIGUSR1) - DECLARE_SIGNAL(SIGUSR2) + //DECLARE_SIGNAL(SIGUSR2) no usage currently ; #undef DECLARE_SIGNAL /* @@ -342,10 +344,11 @@ static void CppcheckSignalHandler(int signo, siginfo_t * info, void * context) #endif const Signalmap_t::const_iterator it=listofsignals.find(signo); const char * const signame = (it==listofsignals.end()) ? "unknown" : it->second.c_str(); - bool printCallstack=true; - bool lowMem=false; - bool unexpectedSignal=true; - const bool isaddressonstack = IsAddressOnStack(info->si_addr); + bool printCallstack=true; // try to print a callstack? + bool lowMem=false; // was low-memory condition detected? + bool unexpectedSignal=true; // unexpected indicates things didn't go as they should... + bool terminate=true; // exit process/thread + const bool isAddressOnStack = IsAddressOnStack(info->si_addr); FILE* output = CppCheckExecutor::getExceptionOutput(); switch (signo) { case SIGABRT: @@ -450,7 +453,7 @@ static void CppcheckSignalHandler(int signo, siginfo_t * info, void * context) } fprintf(output, " (at 0x%lx).%s\n", (unsigned long)info->si_addr, - (isaddressonstack)?" Stackoverflow?":""); + (isAddressOnStack)?" Stackoverflow?":""); break; case SIGINT: unexpectedSignal=false; // legal usage: interrupt application via CTRL-C @@ -476,14 +479,14 @@ static void CppcheckSignalHandler(int signo, siginfo_t * info, void * context) (type==-1)? "" : (type==0) ? "reading " : "writing ", (unsigned long)info->si_addr, - (isaddressonstack)?" Stackoverflow?":"" + (isAddressOnStack)?" Stackoverflow?":"" ); break; case SIGUSR1: - case SIGUSR2: fputs("cppcheck received signal ", output); fputs(signame, output); fputs(".\n", output); + terminate=false; break; default: fputs("Internal error: cppcheck received signal ", output); @@ -499,9 +502,14 @@ static void CppcheckSignalHandler(int signo, siginfo_t * info, void * context) } fflush(output); - // now let things proceed, shutdown and hopefully dump core for post-mortem analysis - signal(signo, SIG_DFL); - kill(killid, signo); + if (terminate) { + // now let things proceed, shutdown and hopefully dump core for post-mortem analysis + struct sigaction act; + memset(&act, 0, sizeof(act)); + act.sa_handler=SIG_DFL; + sigaction(signo, &act, nullptr); + kill(killid, signo); + } } #endif