#7425 Broken XML output due to information about missing include paths. Use stdout for warning message (in alignment with other warnings messages). Minor refactoring (move some function from anon. namespace to static,etc.)

This commit is contained in:
Alexander Mai 2016-05-20 21:32:59 +02:00
parent d676022556
commit 80f445bf6f
1 changed files with 260 additions and 263 deletions

View File

@ -119,7 +119,7 @@ bool CppCheckExecutor::parseFromArgs(CppCheck *cppcheck, int argc, const char* c
else { else {
// If the include path is not found, warn user and remove the non-existing path from the list. // If the include path is not found, warn user and remove the non-existing path from the list.
if (settings.isEnabled("information")) if (settings.isEnabled("information"))
std::cerr << "(information) Couldn't find path given by -I '" << path << '\'' << std::endl; std::cout << "(information) Couldn't find path given by -I '" << path << '\'' << std::endl;
iter = settings.includePaths.erase(iter); iter = settings.includePaths.erase(iter);
} }
} }
@ -179,7 +179,6 @@ int CppCheckExecutor::check(int argc, const char* const argv[])
if (settings.terminated()) { if (settings.terminated()) {
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
if (cppCheck.settings().exceptionHandling) { if (cppCheck.settings().exceptionHandling) {
return check_wrapper(cppCheck, argc, argv); return check_wrapper(cppCheck, argc, argv);
} else { } else {
@ -199,301 +198,299 @@ std::size_t GetArrayLength(const T(&)[size])
#if defined(USE_UNIX_SIGNAL_HANDLING) #if defined(USE_UNIX_SIGNAL_HANDLING)
namespace { /*
/* * Try to print the callstack.
* Try to print the callstack. * That is very sensitive to the operating system, hardware, compiler and runtime!
* 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.
* The code is not meant for production environment, 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)
void print_stacktrace(FILE* output, bool demangling, int maxdepth, bool lowMem) {
{
#if defined(USE_UNIX_BACKTRACE_SUPPORT) #if defined(USE_UNIX_BACKTRACE_SUPPORT)
// 32 vs. 64bit // 32 vs. 64bit
#define ADDRESSDISPLAYLENGTH ((sizeof(long)==8)?12:8) #define ADDRESSDISPLAYLENGTH ((sizeof(long)==8)?12:8)
const int fd = fileno(output); const int fd = fileno(output);
void *array[32]= {0}; // the less resources the better... void *array[32]= {0}; // the less resources the better...
const int currentdepth = backtrace(array, (int)GetArrayLength(array)); const int currentdepth = backtrace(array, (int)GetArrayLength(array));
const int offset=2; // some entries on top are within our own exception handling code or libc const int offset=2; // some entries on top are within our own exception handling code or libc
if (maxdepth<0) if (maxdepth<0)
maxdepth=currentdepth-offset; maxdepth=currentdepth-offset;
else else
maxdepth = std::min(maxdepth, currentdepth); maxdepth = std::min(maxdepth, currentdepth);
if (lowMem) { if (lowMem) {
fputs("Callstack (symbols only):\n", output); fputs("Callstack (symbols only):\n", output);
fflush(output); backtrace_symbols_fd(array+offset, maxdepth, fd);
backtrace_symbols_fd(array+offset, maxdepth, fd); fflush(output);
fflush(output); } else {
} else { char **symbolstrings = backtrace_symbols(array, currentdepth);
char **symbolstrings = backtrace_symbols(array, currentdepth); if (symbolstrings) {
if (symbolstrings) { fputs("Callstack:\n", output);
fputs("Callstack:\n", output); for (int i = offset; i < maxdepth; ++i) {
for (int i = offset; i < maxdepth; ++i) { const char * const symbol = symbolstrings[i];
const char * const symbol = symbolstrings[i]; char * realname = nullptr;
char * realname = nullptr; const char * const firstBracketName = strchr(symbol, '(');
const char * const firstBracketName = strchr(symbol, '('); const char * const firstBracketAddress = strchr(symbol, '[');
const char * const firstBracketAddress = strchr(symbol, '['); const char * const secondBracketAddress = strchr(firstBracketAddress, ']');
const char * const secondBracketAddress = strchr(firstBracketAddress, ']'); const char * const beginAddress = firstBracketAddress+3;
const char * const beginAddress = firstBracketAddress+3; const int addressLen = int(secondBracketAddress-beginAddress);
const int addressLen = int(secondBracketAddress-beginAddress); const int padLen = int(ADDRESSDISPLAYLENGTH-addressLen);
const int padLen = int(ADDRESSDISPLAYLENGTH-addressLen); if (demangling && firstBracketName) {
if (demangling && firstBracketName) { const char * const plus = strchr(firstBracketName, '+');
const char * const plus = strchr(firstBracketName, '+'); if (plus && (plus>(firstBracketName+1))) {
if (plus && (plus>(firstBracketName+1))) { char input_buffer[512]= {0};
char input_buffer[512]= {0}; strncpy(input_buffer, firstBracketName+1, plus-firstBracketName-1);
strncpy(input_buffer, firstBracketName+1, plus-firstBracketName-1); char output_buffer[1024]= {0};
char output_buffer[1024]= {0}; size_t length = GetArrayLength(output_buffer);
size_t length = GetArrayLength(output_buffer); int status=0;
int status=0; realname = abi::__cxa_demangle(input_buffer, output_buffer, &length, &status); // non-NULL on success
realname = abi::__cxa_demangle(input_buffer, output_buffer, &length, &status); // non-NULL on success
}
}
const int ordinal=i-offset;
fprintf(output, "#%-2d 0x",
ordinal);
if (padLen>0)
fprintf(output, "%0*d",
padLen, 0);
if (realname) {
fprintf(output, "%.*s in %s\n",
(int)(secondBracketAddress-firstBracketAddress-3), firstBracketAddress+3,
realname);
} else {
fprintf(output, "%.*s in %.*s\n",
(int)(secondBracketAddress-firstBracketAddress-3), firstBracketAddress+3,
(int)(firstBracketAddress-symbol), symbol);
} }
} }
free(symbolstrings); const int ordinal=i-offset;
} else { fprintf(output, "#%-2d 0x",
fputs("Callstack could not be obtained\n", output); ordinal);
if (padLen>0)
fprintf(output, "%0*d",
padLen, 0);
if (realname) {
fprintf(output, "%.*s in %s\n",
(int)(secondBracketAddress-firstBracketAddress-3), firstBracketAddress+3,
realname);
} else {
fprintf(output, "%.*s in %.*s\n",
(int)(secondBracketAddress-firstBracketAddress-3), firstBracketAddress+3,
(int)(firstBracketAddress-symbol), symbol);
}
} }
free(symbolstrings);
} else {
fputs("Callstack could not be obtained\n", output);
} }
}
#undef ADDRESSDISPLAYLENGTH #undef ADDRESSDISPLAYLENGTH
#endif #endif
} }
const size_t MYSTACKSIZE = 16*1024+SIGSTKSZ; // wild guess about a reasonable buffer static const size_t MYSTACKSIZE = 16*1024+SIGSTKSZ; // wild guess about a reasonable buffer
char mytstack[MYSTACKSIZE]= {0}; // alternative stack for signal handler static char mytstack[MYSTACKSIZE]= {0}; // alternative stack for signal handler
bool bStackBelowHeap=false; // lame attempt to locate heap vs. stack address space. See CppCheckExecutor::check_wrapper() static bool bStackBelowHeap=false; // lame attempt to locate heap vs. stack address space. See CppCheckExecutor::check_wrapper()
/* /*
* \param[in] ptr address to be examined. * \param[in] ptr address to be examined.
* \return true if address is supposed to be on stack (contrary to heap or elsewhere). If ptr is 0 false will be returned. * \return true if address is supposed to be on stack (contrary to heap). If ptr is 0 false will be returned.
* If unknown better return false. * If unknown better return false.
*/ */
bool IsAddressOnStack(const void* ptr) static bool IsAddressOnStack(const void* ptr)
{ {
if (nullptr==ptr) if (nullptr==ptr)
return false; return false;
char a; char a;
if (bStackBelowHeap) if (bStackBelowHeap)
return ptr < &a; return ptr < &a;
else else
return ptr > &a; return ptr > &a;
} }
/* (declare this list here, so it may be used in signal handlers in addition to main()) /* (declare this list here, so it may be used in signal handlers in addition to main())
* A list of signals available in ISO C * A list of signals available in ISO C
* Check out http://pubs.opengroup.org/onlinepubs/009695399/basedefs/signal.h.html * Check out http://pubs.opengroup.org/onlinepubs/009695399/basedefs/signal.h.html
* For now we only want to detect abnormal behaviour for a few selected signals: * For now we only want to detect abnormal behaviour for a few selected signals:
*/ */
#define DECLARE_SIGNAL(x) << std::make_pair(x, #x) #define DECLARE_SIGNAL(x) << std::make_pair(x, #x)
typedef std::map<int, std::string> Signalmap_t; typedef std::map<int, std::string> Signalmap_t;
const Signalmap_t listofsignals = make_container< Signalmap_t > () static const Signalmap_t listofsignals = make_container< Signalmap_t > ()
DECLARE_SIGNAL(SIGABRT) DECLARE_SIGNAL(SIGABRT)
DECLARE_SIGNAL(SIGBUS) DECLARE_SIGNAL(SIGBUS)
DECLARE_SIGNAL(SIGFPE) DECLARE_SIGNAL(SIGFPE)
DECLARE_SIGNAL(SIGILL) DECLARE_SIGNAL(SIGILL)
DECLARE_SIGNAL(SIGINT) DECLARE_SIGNAL(SIGINT)
DECLARE_SIGNAL(SIGQUIT) DECLARE_SIGNAL(SIGQUIT)
DECLARE_SIGNAL(SIGSEGV) DECLARE_SIGNAL(SIGSEGV)
DECLARE_SIGNAL(SIGSYS) DECLARE_SIGNAL(SIGSYS)
// don't care: SIGTERM // don't care: SIGTERM
DECLARE_SIGNAL(SIGUSR1) DECLARE_SIGNAL(SIGUSR1)
DECLARE_SIGNAL(SIGUSR2) DECLARE_SIGNAL(SIGUSR2)
; ;
#undef DECLARE_SIGNAL #undef DECLARE_SIGNAL
/* /*
* Entry pointer for signal handlers * Entry pointer for signal handlers
* It uses functions which are not safe to be called from a signal handler, * It uses functions which are not safe to be called from a signal handler,
* but when ending up here something went terribly wrong anyway. * (http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04 has a whitelist)
* And all which is left is just printing some information and terminate. * but when ending up here something went terribly wrong anyway.
*/ * And all which is left is just printing some information and terminate.
void CppcheckSignalHandler(int signo, siginfo_t * info, void * context) */
{ static void CppcheckSignalHandler(int signo, siginfo_t * info, void * context)
int type = -1; {
pid_t killid = getpid(); int type = -1;
pid_t killid = getpid();
#if defined(__linux__) && defined(REG_ERR) #if defined(__linux__) && defined(REG_ERR)
const ucontext_t* const uc = reinterpret_cast<const ucontext_t*>(context); const ucontext_t* const uc = reinterpret_cast<const ucontext_t*>(context);
killid = (pid_t) syscall(SYS_gettid); killid = (pid_t) syscall(SYS_gettid);
if (uc) { if (uc) {
type = (int)uc->uc_mcontext.gregs[REG_ERR] & 2; type = (int)uc->uc_mcontext.gregs[REG_ERR] & 2;
} }
#endif #endif
const Signalmap_t::const_iterator it=listofsignals.find(signo); const Signalmap_t::const_iterator it=listofsignals.find(signo);
const char * const signame = (it==listofsignals.end()) ? "unknown" : it->second.c_str(); const char * const signame = (it==listofsignals.end()) ? "unknown" : it->second.c_str();
bool printCallstack=true; bool printCallstack=true;
bool lowMem=false; bool lowMem=false;
bool unexpectedSignal=true; bool unexpectedSignal=true;
const bool isaddressonstack = IsAddressOnStack(info->si_addr); const bool isaddressonstack = IsAddressOnStack(info->si_addr);
FILE* output = CppCheckExecutor::getExceptionOutput(); FILE* output = CppCheckExecutor::getExceptionOutput();
switch (signo) { switch (signo) {
case SIGABRT: case SIGABRT:
fputs("Internal error: cppcheck received signal ", output); fputs("Internal error: cppcheck received signal ", output);
fputs(signame, output); fputs(signame, output);
fputs(" - out of memory?\n", output); fputs(" - out of memory?\n", output);
lowMem=true; // educated guess lowMem=true; // educated guess
break;
case SIGBUS:
fputs("Internal error: cppcheck received signal ", output);
fputs(signame, output);
switch (info->si_code) {
case BUS_ADRALN: // invalid address alignment
fputs(" - BUS_ADRALN", output);
break;
case BUS_ADRERR: // nonexistent physical address
fputs(" - BUS_ADRERR", output);
break;
case BUS_OBJERR: // object-specific hardware error
fputs(" - BUS_OBJERR", output);
break; break;
case SIGBUS:
fputs("Internal error: cppcheck received signal ", output);
fputs(signame, output);
switch (info->si_code) {
case BUS_ADRALN: // invalid address alignment
fputs(" - BUS_ADRALN", output);
break;
case BUS_ADRERR: // nonexistent physical address
fputs(" - BUS_ADRERR", output);
break;
case BUS_OBJERR: // object-specific hardware error
fputs(" - BUS_OBJERR", output);
break;
#ifdef BUS_MCEERR_AR #ifdef BUS_MCEERR_AR
case BUS_MCEERR_AR: // Hardware memory error consumed on a machine check; case BUS_MCEERR_AR: // Hardware memory error consumed on a machine check;
fputs(" - BUS_MCEERR_AR", output); fputs(" - BUS_MCEERR_AR", output);
break; break;
#endif #endif
#ifdef BUS_MCEERR_AO #ifdef BUS_MCEERR_AO
case BUS_MCEERR_AO: // Hardware memory error detected in process but not consumed case BUS_MCEERR_AO: // Hardware memory error detected in process but not consumed
fputs(" - BUS_MCEERR_AO", output); fputs(" - BUS_MCEERR_AO", output);
break; break;
#endif #endif
default: default:
break;
}
fprintf(output, " (at 0x%lx).\n",
(unsigned long)info->si_addr);
break; break;
case SIGFPE: }
fputs("Internal error: cppcheck received signal ", output); fprintf(output, " (at 0x%lx).\n",
fputs(signame, output); (unsigned long)info->si_addr);
switch (info->si_code) { break;
case FPE_INTDIV: // integer divide by zero case SIGFPE:
fputs(" - FPE_INTDIV", output); fputs("Internal error: cppcheck received signal ", output);
break; fputs(signame, output);
case FPE_INTOVF: // integer overflow switch (info->si_code) {
fputs(" - FPE_INTOVF", output); case FPE_INTDIV: // integer divide by zero
break; fputs(" - FPE_INTDIV", output);
case FPE_FLTDIV: // floating-point divide by zero
fputs(" - FPE_FLTDIV", output);
break;
case FPE_FLTOVF: // floating-point overflow
fputs(" - FPE_FLTOVF", output);
break;
case FPE_FLTUND: // floating-point underflow
fputs(" - FPE_FLTUND", output);
break;
case FPE_FLTRES: // floating-point inexact result
fputs(" - FPE_FLTRES", output);
break;
case FPE_FLTINV: // floating-point invalid operation
fputs(" - FPE_FLTINV", output);
break;
case FPE_FLTSUB: // subscript out of range
fputs(" - FPE_FLTSUB", output);
break;
default:
break;
}
fprintf(output, " (at 0x%lx).\n",
(unsigned long)info->si_addr);
break; break;
case SIGILL: case FPE_INTOVF: // integer overflow
fputs("Internal error: cppcheck received signal ", output); fputs(" - FPE_INTOVF", output);
fputs(signame, output);
switch (info->si_code) {
case ILL_ILLOPC: // illegal opcode
fputs(" - ILL_ILLOPC", output);
break;
case ILL_ILLOPN: // illegal operand
fputs(" - ILL_ILLOPN", output);
break;
case ILL_ILLADR: // illegal addressing mode
fputs(" - ILL_ILLADR", output);
break;
case ILL_ILLTRP: // illegal trap
fputs(" - ILL_ILLTRP", output);
break;
case ILL_PRVOPC: // privileged opcode
fputs(" - ILL_PRVOPC", output);
break;
case ILL_PRVREG: // privileged register
fputs(" - ILL_PRVREG", output);
break;
case ILL_COPROC: // coprocessor error
fputs(" - ILL_COPROC", output);
break;
case ILL_BADSTK: // internal stack error
fputs(" - ILL_BADSTK", output);
break;
default:
break;
}
fprintf(output, " (at 0x%lx).%s\n",
(unsigned long)info->si_addr,
(isaddressonstack)?" Stackoverflow?":"");
break; break;
case SIGINT: case FPE_FLTDIV: // floating-point divide by zero
unexpectedSignal=false; fputs(" - FPE_FLTDIV", output);
fputs("cppcheck received signal ", output);
fputs(signame, output);
printCallstack=true;
fputs(".\n", output);
break; break;
case SIGSEGV: case FPE_FLTOVF: // floating-point overflow
fputs("Internal error: cppcheck received signal ", output); fputs(" - FPE_FLTOVF", output);
fputs(signame, output);
switch (info->si_code) {
case SEGV_MAPERR: // address not mapped to object
fputs(" - SEGV_MAPERR", output);
break;
case SEGV_ACCERR: // invalid permissions for mapped object
fputs(" - SEGV_ACCERR", output);
break;
default:
break;
}
fprintf(output, " (%sat 0x%lx).%s\n",
(type==-1)? "" :
(type==0) ? "reading " : "writing ",
(unsigned long)info->si_addr,
(isaddressonstack)?" Stackoverflow?":""
);
break; break;
case SIGUSR1: case FPE_FLTUND: // floating-point underflow
unexpectedSignal=false; fputs(" - FPE_FLTUND", output);
fputs("cppcheck received signal ", output); break;
fputs(signame, output); case FPE_FLTRES: // floating-point inexact result
fputs(".\n", output); fputs(" - FPE_FLTRES", output);
break;
case FPE_FLTINV: // floating-point invalid operation
fputs(" - FPE_FLTINV", output);
break;
case FPE_FLTSUB: // subscript out of range
fputs(" - FPE_FLTSUB", output);
break; break;
default: default:
fputs("Internal error: cppcheck received signal ", output);
fputs(signame, output);
fputs(".\n", output);
break; break;
} }
if (printCallstack) { fprintf(output, " (at 0x%lx).\n",
print_stacktrace(output, true, -1, lowMem); (unsigned long)info->si_addr);
break;
case SIGILL:
fputs("Internal error: cppcheck received signal ", output);
fputs(signame, output);
switch (info->si_code) {
case ILL_ILLOPC: // illegal opcode
fputs(" - ILL_ILLOPC", output);
break;
case ILL_ILLOPN: // illegal operand
fputs(" - ILL_ILLOPN", output);
break;
case ILL_ILLADR: // illegal addressing mode
fputs(" - ILL_ILLADR", output);
break;
case ILL_ILLTRP: // illegal trap
fputs(" - ILL_ILLTRP", output);
break;
case ILL_PRVOPC: // privileged opcode
fputs(" - ILL_PRVOPC", output);
break;
case ILL_PRVREG: // privileged register
fputs(" - ILL_PRVREG", output);
break;
case ILL_COPROC: // coprocessor error
fputs(" - ILL_COPROC", output);
break;
case ILL_BADSTK: // internal stack error
fputs(" - ILL_BADSTK", output);
break;
default:
break;
} }
if (unexpectedSignal) { fprintf(output, " (at 0x%lx).%s\n",
fputs("\nPlease report this to the cppcheck developers!\n", output); (unsigned long)info->si_addr,
(isaddressonstack)?" Stackoverflow?":"");
break;
case SIGINT:
unexpectedSignal=false; // legal usage: interrupt application via CTRL-C
fputs("cppcheck received signal ", output);
fputs(signame, output);
printCallstack=true;
fputs(".\n", output);
break;
case SIGSEGV:
fputs("Internal error: cppcheck received signal ", output);
fputs(signame, output);
switch (info->si_code) {
case SEGV_MAPERR: // address not mapped to object
fputs(" - SEGV_MAPERR", output);
break;
case SEGV_ACCERR: // invalid permissions for mapped object
fputs(" - SEGV_ACCERR", output);
break;
default:
break;
} }
fflush(output); fprintf(output, " (%sat 0x%lx).%s\n",
(type==-1)? "" :
// now let things proceed, shutdown and hopefully dump core for post-mortem analysis (type==0) ? "reading " : "writing ",
signal(signo, SIG_DFL); (unsigned long)info->si_addr,
kill(killid, signo); (isaddressonstack)?" Stackoverflow?":""
);
break;
case SIGUSR1:
case SIGUSR2:
fputs("cppcheck received signal ", output);
fputs(signame, output);
fputs(".\n", output);
break;
default:
fputs("Internal error: cppcheck received signal ", output);
fputs(signame, output);
fputs(".\n", output);
break;
} }
if (printCallstack) {
print_stacktrace(output, true, -1, lowMem);
}
if (unexpectedSignal) {
fputs("\nPlease report this to the cppcheck developers!\n", output);
}
fflush(output);
// now let things proceed, shutdown and hopefully dump core for post-mortem analysis
signal(signo, SIG_DFL);
kill(killid, signo);
} }
#endif #endif