2008-12-18 22:28:57 +01:00
/*
2009-01-21 21:04:20 +01:00
* Cppcheck - A tool for static C / C + + code analysis
2015-01-03 12:14:58 +01:00
* Copyright ( C ) 2007 - 2015 Daniel Marjamäki and Cppcheck team .
2008-12-18 22:28:57 +01:00
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
2009-09-27 17:08:31 +02:00
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
2008-12-18 22:28:57 +01:00
*/
# include "cppcheckexecutor.h"
2013-09-04 06:18:22 +02:00
# include "cmdlineparser.h"
2008-12-18 22:28:57 +01:00
# include "cppcheck.h"
2011-05-02 14:58:16 +02:00
# include "errorlogger.h"
2013-09-04 06:18:22 +02:00
# include "filelister.h"
# include "path.h"
# include "pathmatch.h"
# include "preprocessor.h"
# include "threadexecutor.h"
2014-06-28 14:05:18 +02:00
# include <climits>
2009-03-06 01:03:31 +01:00
# include <cstdlib> // EXIT_SUCCESS and EXIT_FAILURE
2011-08-11 16:34:59 +02:00
# include <cstring>
2011-10-09 20:14:44 +02:00
# include <algorithm>
2014-06-28 14:05:18 +02:00
# include <iostream>
# include <sstream>
2011-10-09 20:14:44 +02:00
2014-11-02 15:47:55 +01:00
# if !defined(NO_UNIX_SIGNAL_HANDLING) && defined(__GNUC__) && !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(__OS2__)
2014-03-16 12:04:13 +01:00
# define USE_UNIX_SIGNAL_HANDLING
2014-03-18 21:14:09 +01:00
# include <cstdio>
2014-11-14 23:40:53 +01:00
# include <signal.h>
# include <unistd.h>
2014-11-15 20:10:34 +01:00
# if defined(__APPLE__)
# define _XOPEN_SOURCE // ucontext.h APIs can only be used on Mac OSX >= 10.7 if _XOPEN_SOURCE is defined
# include <ucontext.h>
# undef _XOPEN_SOURCE
# else
# include <ucontext.h>
# endif
2014-11-14 23:40:53 +01:00
# ifdef __linux__
# include <sys/syscall.h>
# include <sys/types.h>
# endif
2014-03-16 12:04:13 +01:00
# endif
2014-12-16 16:11:25 +01:00
# if !defined(NO_UNIX_BACKTRACE_SUPPORT) && defined(USE_UNIX_SIGNAL_HANDLING) && defined(__GNUC__) && !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(__NetBSD__) && !defined(__SVR4) && !defined(__QNX__)
2014-06-28 14:05:18 +02:00
# define USE_UNIX_BACKTRACE_SUPPORT
# include <cxxabi.h>
# include <execinfo.h>
# endif
2014-03-22 09:57:43 +01:00
# if defined(_MSC_VER)
2014-03-17 19:11:00 +01:00
# define USE_WINDOWS_SEH
2014-03-16 12:04:13 +01:00
# include <Windows.h>
2014-06-29 18:57:48 +02:00
# include <DbgHelp.h>
2014-03-16 12:04:13 +01:00
# include <excpt.h>
2014-06-29 18:57:48 +02:00
# include <TCHAR.H>
2014-03-16 12:04:13 +01:00
# endif
2008-12-18 22:28:57 +01:00
CppCheckExecutor : : CppCheckExecutor ( )
2012-04-07 15:36:45 +02:00
: _settings ( 0 ) , time1 ( 0 ) , errorlist ( false )
2008-12-18 22:28:57 +01:00
{
}
CppCheckExecutor : : ~ CppCheckExecutor ( )
{
}
2010-08-31 20:32:26 +02:00
bool CppCheckExecutor : : parseFromArgs ( CppCheck * cppcheck , int argc , const char * const argv [ ] )
{
2012-04-06 14:19:26 +02:00
Settings & settings = cppcheck - > settings ( ) ;
CmdLineParser parser ( & settings ) ;
2014-05-29 16:57:45 +02:00
const bool success = parser . ParseFromArgs ( argc , argv ) ;
2010-08-31 20:32:26 +02:00
2011-10-13 20:53:06 +02:00
if ( success ) {
if ( parser . GetShowVersion ( ) & & ! parser . GetShowErrorMessages ( ) ) {
2011-08-11 16:34:59 +02:00
const char * extraVersion = cppcheck - > extraVersion ( ) ;
2012-02-29 20:57:48 +01:00
if ( * extraVersion ! = 0 )
2011-08-11 16:34:59 +02:00
std : : cout < < " Cppcheck " < < cppcheck - > version ( ) < < " ( "
2012-02-18 11:55:05 +01:00
< < extraVersion < < ' ) ' < < std : : endl ;
2011-08-11 16:34:59 +02:00
else
std : : cout < < " Cppcheck " < < cppcheck - > version ( ) < < std : : endl ;
2010-08-31 20:32:26 +02:00
}
2011-10-13 20:53:06 +02:00
if ( parser . GetShowErrorMessages ( ) ) {
2011-01-16 17:18:09 +01:00
errorlist = true ;
2012-04-06 14:19:26 +02:00
std : : cout < < ErrorLogger : : ErrorMessage : : getXMLHeader ( settings . _xml_version ) ;
2010-08-31 20:32:26 +02:00
cppcheck - > getErrorMessages ( ) ;
2012-04-06 14:19:26 +02:00
std : : cout < < ErrorLogger : : ErrorMessage : : getXMLFooter ( settings . _xml_version ) < < std : : endl ;
2010-08-31 20:32:26 +02:00
}
2011-01-27 09:30:53 +01:00
2014-06-05 09:28:04 +02:00
if ( parser . ExitAfterPrinting ( ) ) {
settings . terminate ( ) ;
return true ;
}
2011-11-05 18:15:03 +01:00
} else {
2014-06-05 09:28:04 +02:00
return false ;
2010-08-31 20:32:26 +02:00
}
2011-01-09 09:29:38 +01:00
// Check that all include paths exist
{
2011-04-16 11:19:56 +02:00
std : : list < std : : string > : : iterator iter ;
2012-04-06 14:19:26 +02:00
for ( iter = settings . _includePaths . begin ( ) ;
iter ! = settings . _includePaths . end ( ) ;
2011-10-13 20:53:06 +02:00
) {
2011-01-11 20:03:18 +01:00
const std : : string path ( Path : : toNativeSeparators ( * iter ) ) ;
2011-04-16 11:19:56 +02:00
if ( FileLister : : isDirectory ( path ) )
+ + iter ;
2011-10-13 20:53:06 +02:00
else {
2014-01-10 21:50:21 +01:00
// If the include path is not found, warn user (unless --quiet
// was used) and remove the non-existing path from the list.
if ( ! settings . _errorsOnly )
std : : cout < < " cppcheck: warning: Couldn't find path given by -I ' " < < path < < ' \' ' < < std : : endl ;
2012-04-06 14:19:26 +02:00
iter = settings . _includePaths . erase ( iter ) ;
2011-01-09 09:29:38 +01:00
}
}
}
2012-02-19 17:22:59 +01:00
const std : : vector < std : : string > & pathnames = parser . GetPathNames ( ) ;
2010-08-31 20:32:26 +02:00
2011-10-13 20:53:06 +02:00
if ( ! pathnames . empty ( ) ) {
2010-08-31 20:32:26 +02:00
// Execute recursiveAddFiles() to each given file parameter
std : : vector < std : : string > : : const_iterator iter ;
for ( iter = pathnames . begin ( ) ; iter ! = pathnames . end ( ) ; + + iter )
2013-10-31 19:09:01 +01:00
FileLister : : recursiveAddFiles ( _files , Path : : toNativeSeparators ( * iter ) , _settings - > library . markupExtensions ( ) ) ;
2010-08-31 20:32:26 +02:00
}
2012-02-19 17:22:59 +01:00
if ( ! _files . empty ( ) ) {
2011-08-06 11:29:51 +02:00
// Remove header files from the list of ignored files.
// Also output a warning for the user.
// TODO: Remove all unknown files? (use FileLister::acceptFile())
2012-01-01 20:17:16 +01:00
bool warn = false ;
2011-08-06 11:29:51 +02:00
std : : vector < std : : string > ignored = parser . GetIgnoredPaths ( ) ;
2012-01-01 20:17:16 +01:00
for ( std : : vector < std : : string > : : iterator i = ignored . begin ( ) ; i ! = ignored . end ( ) ; ) {
const std : : string extension = Path : : getFilenameExtension ( * i ) ;
2011-10-13 20:53:06 +02:00
if ( extension = = " .h " | | extension = = " .hpp " ) {
2012-01-01 20:17:16 +01:00
i = ignored . erase ( i ) ;
warn = true ;
2011-11-01 13:07:45 +01:00
} else
+ + i ;
2011-08-06 11:29:51 +02:00
}
2012-01-01 20:17:16 +01:00
if ( warn ) {
std : : cout < < " cppcheck: filename exclusion does not apply to header (.h and .hpp) files. " < < std : : endl ;
std : : cout < < " cppcheck: Please use --suppress for ignoring results from the header files. " < < std : : endl ;
}
2011-08-06 11:29:51 +02:00
2011-10-02 11:02:07 +02:00
# if defined(_WIN32)
2012-02-19 17:22:59 +01:00
// For Windows we want case-insensitive path matching
const bool caseSensitive = false ;
2011-10-02 11:02:07 +02:00
# else
2012-02-19 17:22:59 +01:00
const bool caseSensitive = true ;
2011-10-02 11:02:07 +02:00
# endif
2012-02-19 17:22:59 +01:00
PathMatch matcher ( parser . GetIgnoredPaths ( ) , caseSensitive ) ;
2012-07-08 23:39:46 +02:00
for ( std : : map < std : : string , std : : size_t > : : iterator i = _files . begin ( ) ; i ! = _files . end ( ) ; ) {
2012-02-19 17:22:59 +01:00
if ( matcher . Match ( i - > first ) )
_files . erase ( i + + ) ;
2011-11-01 13:07:45 +01:00
else
+ + i ;
2011-01-31 14:25:51 +01:00
}
2011-10-13 20:53:06 +02:00
} else {
2010-10-22 17:09:50 +02:00
std : : cout < < " cppcheck: error: could not find or open any of the paths given. " < < std : : endl ;
return false ;
}
2011-01-31 14:25:51 +01:00
2014-09-02 16:10:51 +02:00
if ( _files . empty ( ) ) {
2011-01-31 14:25:51 +01:00
std : : cout < < " cppcheck: error: no files to check - all paths ignored. " < < std : : endl ;
return false ;
}
2014-09-02 16:10:51 +02:00
return true ;
2010-08-31 20:32:26 +02:00
}
2009-03-06 01:03:31 +01:00
int CppCheckExecutor : : check ( int argc , const char * const argv [ ] )
2008-12-18 22:28:57 +01:00
{
2011-05-02 14:58:16 +02:00
Preprocessor : : missingIncludeFlag = false ;
2014-05-03 19:31:15 +02:00
Preprocessor : : missingSystemIncludeFlag = false ;
2011-05-02 14:58:16 +02:00
2011-02-16 02:12:15 +01:00
CppCheck cppCheck ( * this , true ) ;
2009-02-19 23:21:18 +01:00
2012-04-06 14:19:26 +02:00
Settings & settings = cppCheck . settings ( ) ;
_settings = & settings ;
2012-04-08 10:05:44 +02:00
if ( ! parseFromArgs ( & cppCheck , argc , argv ) ) {
return EXIT_FAILURE ;
}
2014-06-05 09:28:04 +02:00
if ( settings . terminated ( ) ) {
return EXIT_SUCCESS ;
}
2012-04-08 10:05:44 +02:00
2014-03-16 12:04:13 +01:00
if ( cppCheck . settings ( ) . exceptionHandling ) {
return check_wrapper ( cppCheck , argc , argv ) ;
} else {
return check_internal ( cppCheck , argc , argv ) ;
}
}
2014-06-29 18:57:48 +02:00
/**
* Simple helper function :
* \ return size of array
* */
template < typename T , int size >
size_t GetArrayLength ( const T ( & ) [ size ] )
{
return size ;
}
2014-03-16 12:04:13 +01:00
# if defined(USE_UNIX_SIGNAL_HANDLING)
/* (declare this list here, so it may be used in signal handlers in addition to main())
* A list of signals available in ISO C
* 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 :
*/
2014-03-16 18:37:28 +01:00
struct Signaltype {
int signalnumber ;
const char * signalname ;
} ;
# define DECLARE_SIGNAL(x) {x, #x}
static const Signaltype listofsignals [ ] = {
// don't care: SIGABRT,
2014-05-25 15:53:26 +02:00
DECLARE_SIGNAL ( SIGBUS ) ,
2014-03-16 18:37:28 +01:00
DECLARE_SIGNAL ( SIGFPE ) ,
DECLARE_SIGNAL ( SIGILL ) ,
DECLARE_SIGNAL ( SIGINT ) ,
DECLARE_SIGNAL ( SIGSEGV ) ,
// don't care: SIGTERM
2014-03-16 12:04:13 +01:00
} ;
2014-05-11 13:25:36 +02:00
/*
* Simple mapping
*/
static const char * signal_name ( int signo )
{
for ( size_t s = 0 ; s < GetArrayLength ( listofsignals ) ; + + s ) {
if ( listofsignals [ s ] . signalnumber = = signo )
return listofsignals [ s ] . signalname ;
}
return " " ;
}
2014-03-16 18:37:28 +01:00
/*
* Try to print the callstack .
* That is very sensitive to the operating system , hardware , compiler and runtime !
2014-05-17 10:40:48 +02:00
* The code is not meant for production environment , it ' s using functions not whitelisted for usage in a signal handler function .
2014-03-16 18:37:28 +01:00
*/
2015-03-07 18:15:25 +01:00
static void print_stacktrace ( FILE * f , bool demangling , int maxdepth )
2014-03-16 12:04:13 +01:00
{
2014-06-28 14:05:18 +02:00
# if defined(USE_UNIX_BACKTRACE_SUPPORT)
2015-03-08 14:24:54 +01:00
// 32 vs. 64bit
# define ADDRESSDISPLAYLENGTH ((sizeof(long)==8)?12:8)
2014-03-30 21:29:17 +02:00
void * array [ 32 ] = { 0 } ; // the less resources the better...
2014-03-16 18:37:28 +01:00
const int depth = backtrace ( array , ( int ) GetArrayLength ( array ) ) ;
2015-03-07 18:15:25 +01:00
const int offset = 3 ; // the first two entries are simply within our own exception handling code, third is within libc
if ( maxdepth < 0 )
maxdepth = depth + offset ;
else
maxdepth + = offset ;
2014-03-16 18:37:28 +01:00
char * * symbolstrings = backtrace_symbols ( array , depth ) ;
if ( symbolstrings ) {
2014-03-30 21:29:17 +02:00
fputs ( " Callstack: \n " , f ) ;
2015-03-07 18:15:25 +01:00
for ( int i = offset ; i < maxdepth ; + + i ) {
2014-03-16 18:37:28 +01:00
const char * const symbol = symbolstrings [ i ] ;
char * realname = nullptr ;
2014-03-30 21:29:17 +02:00
const char * const firstBracketName = strchr ( symbol , ' ( ' ) ;
const char * const firstBracketAddress = strchr ( symbol , ' [ ' ) ;
const char * const secondBracketAddress = strchr ( firstBracketAddress , ' ] ' ) ;
const char * const beginAddress = firstBracketAddress + 3 ;
const int addressLen = int ( secondBracketAddress - beginAddress ) ;
const int padLen = int ( ADDRESSDISPLAYLENGTH - addressLen ) ;
if ( demangling & & firstBracketName ) {
const char * const plus = strchr ( firstBracketName , ' + ' ) ;
if ( plus & & ( plus > ( firstBracketName + 1 ) ) ) {
2014-03-16 18:37:28 +01:00
char input_buffer [ 512 ] = { 0 } ;
2014-03-30 21:29:17 +02:00
strncpy ( input_buffer , firstBracketName + 1 , plus - firstBracketName - 1 ) ;
2014-03-16 18:37:28 +01:00
char output_buffer [ 1024 ] = { 0 } ;
size_t length = GetArrayLength ( output_buffer ) ;
int status = 0 ;
realname = abi : : __cxa_demangle ( input_buffer , output_buffer , & length , & status ) ; // non-NULL on success
}
}
2014-05-17 10:40:48 +02:00
const int ordinal = i - offset ;
fprintf ( f , " #%-2d 0x " ,
ordinal ) ;
2014-03-31 03:06:57 +02:00
if ( padLen > 0 )
fprintf ( f , " %0*d " ,
2014-03-30 21:29:17 +02:00
padLen , 0 ) ;
if ( realname ) {
2014-03-31 03:06:57 +02:00
fprintf ( f , " %.*s in %s \n " ,
2014-03-30 21:29:17 +02:00
( int ) ( secondBracketAddress - firstBracketAddress - 3 ) , firstBracketAddress + 3 ,
realname ) ;
2014-03-31 03:06:57 +02:00
} else {
2014-03-30 21:29:17 +02:00
fprintf ( f , " %.*s in %.*s \n " ,
( int ) ( secondBracketAddress - firstBracketAddress - 3 ) , firstBracketAddress + 3 ,
( int ) ( firstBracketAddress - symbol ) , symbol ) ;
2014-03-31 03:06:57 +02:00
}
2014-03-16 18:37:28 +01:00
}
free ( symbolstrings ) ;
} else {
2014-03-30 21:29:17 +02:00
fputs ( " Callstack could not be obtained \n " , f ) ;
2014-03-16 12:04:13 +01:00
}
2015-03-08 14:24:54 +01:00
# undef ADDRESSDISPLAYLENGTH
2014-03-16 12:04:13 +01:00
# endif
}
2015-03-07 20:47:27 +01:00
static const size_t MYSTACKSIZE = 16 * 1024 + SIGSTKSZ ;
static char mytstack [ MYSTACKSIZE ] ; // alternative stack for signal handler
static bool bStackBelowHeap = false ;
2015-03-07 18:15:25 +01:00
/*
2015-04-01 21:17:13 +02:00
* \ return true if address is supposed to be on stack ( contrary to heap or elsewhere ) . If ptr is 0 false will be returned .
2015-03-07 20:47:27 +01:00
* If unknown better return false .
2015-03-07 18:15:25 +01:00
*/
static bool isAddressOnStack ( const void * ptr )
{
2015-04-01 21:17:13 +02:00
if ( nullptr = = ptr )
return false ;
2015-03-07 18:15:25 +01:00
char a ;
2015-03-07 20:47:27 +01:00
if ( bStackBelowHeap )
return ptr < & a ;
else
return ptr > & a ;
2015-03-07 18:15:25 +01:00
}
2014-03-16 18:37:28 +01:00
/*
* Entry pointer for signal handlers
2014-11-14 23:40:53 +01:00
* It uses functions which are not safe to be called from a signal handler ,
* but when ending up here something went terribly wrong anyway .
* And all which is left is just printing some information and terminate .
2014-03-16 18:37:28 +01:00
*/
2014-11-14 23:40:53 +01:00
static void CppcheckSignalHandler ( int signo , siginfo_t * info , void * context )
2014-03-16 18:37:28 +01:00
{
2014-11-14 23:40:53 +01:00
int type = - 1 ;
pid_t killid = getpid ( ) ;
2015-04-01 21:17:13 +02:00
const ucontext_t * const uc = reinterpret_cast < const ucontext_t * > ( context ) ;
2014-12-31 01:44:50 +01:00
# if defined(__linux__) && defined(REG_ERR)
2014-11-14 23:40:53 +01:00
killid = ( pid_t ) syscall ( SYS_gettid ) ;
if ( uc ) {
type = ( int ) uc - > uc_mcontext . gregs [ REG_ERR ] & 2 ;
}
# endif
2014-05-11 13:25:36 +02:00
const char * const signame = signal_name ( signo ) ;
const char * const sigtext = strsignal ( signo ) ;
2014-03-16 18:37:28 +01:00
bool bPrintCallstack = true ;
2015-03-07 18:15:25 +01:00
const bool isaddressonstack = isAddressOnStack ( info - > si_addr ) ;
2015-04-01 21:17:13 +02:00
FILE * f = ( CppCheckExecutor : : getExceptionOutput ( ) = = " stderr " ) ? stderr : stdout ;
2014-05-11 13:25:36 +02:00
fputs ( " Internal error: cppcheck received signal " , f ) ;
fputs ( signame , f ) ;
fputs ( " , " , f ) ;
fputs ( sigtext , f ) ;
2014-03-16 18:37:28 +01:00
switch ( signo ) {
2014-05-25 15:53:26 +02:00
case SIGBUS :
switch ( info - > si_code ) {
case BUS_ADRALN : // invalid address alignment
2014-11-14 23:40:53 +01:00
fputs ( " - BUS_ADRALN " , f ) ;
2014-05-25 15:53:26 +02:00
break ;
case BUS_ADRERR : // nonexistent physical address
2014-11-14 23:40:53 +01:00
fputs ( " - BUS_ADRERR " , f ) ;
2014-05-25 15:53:26 +02:00
break ;
case BUS_OBJERR : // object-specific hardware error
2014-11-14 23:40:53 +01:00
fputs ( " - BUS_OBJERR " , f ) ;
2014-05-25 15:53:26 +02:00
break ;
# ifdef BUS_MCEERR_AR
case BUS_MCEERR_AR : // Hardware memory error consumed on a machine check;
2014-11-14 23:40:53 +01:00
fputs ( " - BUS_MCEERR_AR " , f ) ;
2014-05-25 15:53:26 +02:00
break ;
# endif
# ifdef BUS_MCEERR_AO
case BUS_MCEERR_AO : // Hardware memory error detected in process but not consumed
2014-11-14 23:40:53 +01:00
fputs ( " - BUS_MCEERR_AO " , f ) ;
2014-05-25 15:53:26 +02:00
break ;
# endif
default :
break ;
}
2015-04-01 21:17:13 +02:00
fprintf ( f , " (at 0x%lx). \n " ,
( unsigned long ) info - > si_addr ) ;
2014-05-29 16:57:45 +02:00
break ;
2014-03-16 18:37:28 +01:00
case SIGFPE :
2014-05-25 15:53:26 +02:00
switch ( info - > si_code ) {
case FPE_INTDIV : // integer divide by zero
2014-11-14 23:40:53 +01:00
fputs ( " - FPE_INTDIV " , f ) ;
2014-05-25 15:53:26 +02:00
break ;
case FPE_INTOVF : // integer overflow
2014-11-14 23:40:53 +01:00
fputs ( " - FPE_INTOVF " , f ) ;
2014-05-25 15:53:26 +02:00
break ;
case FPE_FLTDIV : // floating-point divide by zero
2014-11-14 23:40:53 +01:00
fputs ( " - FPE_FLTDIV " , f ) ;
2014-05-25 15:53:26 +02:00
break ;
case FPE_FLTOVF : // floating-point overflow
2014-11-14 23:40:53 +01:00
fputs ( " - FPE_FLTOVF " , f ) ;
2014-05-25 15:53:26 +02:00
break ;
case FPE_FLTUND : // floating-point underflow
2014-11-14 23:40:53 +01:00
fputs ( " - FPE_FLTUND " , f ) ;
2014-05-25 15:53:26 +02:00
break ;
case FPE_FLTRES : // floating-point inexact result
2014-11-14 23:40:53 +01:00
fputs ( " - FPE_FLTRES " , f ) ;
2014-05-25 15:53:26 +02:00
break ;
case FPE_FLTINV : // floating-point invalid operation
2014-11-14 23:40:53 +01:00
fputs ( " - FPE_FLTINV " , f ) ;
2014-05-25 15:53:26 +02:00
break ;
case FPE_FLTSUB : // subscript out of range
2014-11-14 23:40:53 +01:00
fputs ( " - FPE_FLTSUB " , f ) ;
2014-05-25 15:53:26 +02:00
break ;
default :
break ;
}
2015-04-01 21:17:13 +02:00
fprintf ( f , " (at 0x%lx). \n " ,
( unsigned long ) info - > si_addr ) ;
2014-03-16 18:37:28 +01:00
break ;
2014-05-25 15:53:26 +02:00
case SIGILL :
switch ( info - > si_code ) {
case ILL_ILLOPC : // illegal opcode
2014-11-14 23:40:53 +01:00
fputs ( " - ILL_ILLOPC " , f ) ;
2014-05-25 15:53:26 +02:00
break ;
case ILL_ILLOPN : // illegal operand
2014-11-14 23:40:53 +01:00
fputs ( " - ILL_ILLOPN " , f ) ;
2014-05-25 15:53:26 +02:00
break ;
case ILL_ILLADR : // illegal addressing mode
2014-11-14 23:40:53 +01:00
fputs ( " - ILL_ILLADR " , f ) ;
2014-05-25 15:53:26 +02:00
break ;
case ILL_ILLTRP : // illegal trap
2014-11-14 23:40:53 +01:00
fputs ( " - ILL_ILLTRP " , f ) ;
2014-05-25 15:53:26 +02:00
break ;
case ILL_PRVOPC : // privileged opcode
2014-11-14 23:40:53 +01:00
fputs ( " - ILL_PRVOPC " , f ) ;
2014-05-25 15:53:26 +02:00
break ;
case ILL_PRVREG : // privileged register
2014-11-14 23:40:53 +01:00
fputs ( " - ILL_PRVREG " , f ) ;
2014-05-25 15:53:26 +02:00
break ;
case ILL_COPROC : // coprocessor error
2014-11-14 23:40:53 +01:00
fputs ( " - ILL_COPROC " , f ) ;
2014-05-25 15:53:26 +02:00
break ;
case ILL_BADSTK : // internal stack error
2014-11-14 23:40:53 +01:00
fputs ( " - ILL_BADSTK " , f ) ;
2014-05-25 15:53:26 +02:00
break ;
default :
break ;
}
2015-04-01 21:17:13 +02:00
fprintf ( f , " (at 0x%lx).%s \n " ,
( unsigned long ) info - > si_addr ,
2015-03-07 18:15:25 +01:00
( isaddressonstack ) ? " Stackoverflow? " : " " ) ;
2014-03-16 18:37:28 +01:00
break ;
case SIGINT :
2014-03-10 02:21:44 +01:00
bPrintCallstack = false ;
2014-11-14 23:40:53 +01:00
fputs ( " . \n " , f ) ;
2014-03-10 02:21:44 +01:00
break ;
2014-05-25 15:53:26 +02:00
case SIGSEGV :
switch ( info - > si_code ) {
case SEGV_MAPERR : // address not mapped to object
2014-11-14 23:40:53 +01:00
fputs ( " - SEGV_MAPERR " , f ) ;
2014-05-25 15:53:26 +02:00
break ;
case SEGV_ACCERR : // invalid permissions for mapped object
2014-11-14 23:40:53 +01:00
fputs ( " - SEGV_ACCERR " , f ) ;
2014-05-25 15:53:26 +02:00
break ;
default :
break ;
}
2015-04-01 21:17:13 +02:00
fprintf ( f , " (%sat 0x%lx).%s \n " ,
2014-11-14 23:40:53 +01:00
( type = = - 1 ) ? " " :
( type = = 0 ) ? " reading " : " writing " ,
2015-04-01 21:17:13 +02:00
( unsigned long ) info - > si_addr ,
2015-03-07 18:15:25 +01:00
( isaddressonstack ) ? " Stackoverflow? " : " "
) ;
2014-05-25 15:53:26 +02:00
break ;
2014-03-16 18:37:28 +01:00
default :
2014-05-11 13:25:36 +02:00
fputs ( " . \n " , f ) ;
2014-03-16 18:37:28 +01:00
break ;
}
if ( bPrintCallstack ) {
2015-03-07 18:15:25 +01:00
print_stacktrace ( f , true , - 1 /*(isaddressonstack)?8:-1*/ ) ;
2014-03-30 21:29:17 +02:00
fputs ( " \n Please report this to the cppcheck developers! \n " , f ) ;
2014-03-16 18:37:28 +01:00
}
2015-04-01 21:17:13 +02:00
fflush ( f ) ;
2014-11-14 23:40:53 +01:00
// now let the system proceed, shutdown and hopefully dump core for post-mortem analysis
signal ( signo , SIG_DFL ) ;
kill ( killid , signo ) ;
2014-03-16 12:04:13 +01:00
}
# endif
2014-03-17 19:11:00 +01:00
# ifdef USE_WINDOWS_SEH
2014-06-29 18:57:48 +02:00
static const ULONG maxnamelength = 512 ;
struct IMAGEHLP_SYMBOL64_EXT : public IMAGEHLP_SYMBOL64 {
2014-06-30 12:48:42 +02:00
TCHAR NameExt [ maxnamelength ] ; // actually no need to worry about character encoding here
2014-06-29 18:57:48 +02:00
} ;
typedef BOOL ( WINAPI * fpStackWalk64 ) ( DWORD , HANDLE , HANDLE , LPSTACKFRAME64 , PVOID , PREAD_PROCESS_MEMORY_ROUTINE64 , PFUNCTION_TABLE_ACCESS_ROUTINE64 , PGET_MODULE_BASE_ROUTINE64 , PTRANSLATE_ADDRESS_ROUTINE64 ) ;
static fpStackWalk64 pStackWalk64 ;
2014-06-29 22:53:52 +02:00
typedef DWORD64 ( WINAPI * fpSymGetModuleBase64 ) ( HANDLE , DWORD64 ) ;
2014-06-29 18:57:48 +02:00
static fpSymGetModuleBase64 pSymGetModuleBase64 ;
typedef BOOL ( WINAPI * fpSymGetSymFromAddr64 ) ( HANDLE , DWORD64 , PDWORD64 , PIMAGEHLP_SYMBOL64 ) ;
static fpSymGetSymFromAddr64 pSymGetSymFromAddr64 ;
typedef BOOL ( WINAPI * fpSymGetLineFromAddr64 ) ( HANDLE , DWORD64 , PDWORD , PIMAGEHLP_LINE64 ) ;
2014-06-29 22:53:52 +02:00
static fpSymGetLineFromAddr64 pSymGetLineFromAddr64 ;
typedef DWORD ( WINAPI * fpUnDecorateSymbolName ) ( const TCHAR * , PTSTR , DWORD , DWORD ) ;
static fpUnDecorateSymbolName pUnDecorateSymbolName ;
typedef PVOID ( WINAPI * fpSymFunctionTableAccess64 ) ( HANDLE , DWORD64 ) ;
2014-06-29 18:57:48 +02:00
static fpSymFunctionTableAccess64 pSymFunctionTableAccess64 ;
typedef BOOL ( WINAPI * fpSymInitialize ) ( HANDLE , PCSTR , BOOL ) ;
static fpSymInitialize pSymInitialize ;
2014-07-07 21:25:30 +02:00
static HMODULE hLibDbgHelp ;
2014-06-29 18:57:48 +02:00
// avoid explicit dependency on Dbghelp.dll
static bool loadDbgHelp ( )
{
2014-07-07 21:25:30 +02:00
hLibDbgHelp = : : LoadLibraryW ( L " Dbghelp.dll " ) ;
if ( ! hLibDbgHelp )
2014-06-29 22:53:52 +02:00
return true ;
2014-07-07 21:25:30 +02:00
pStackWalk64 = ( fpStackWalk64 ) : : GetProcAddress ( hLibDbgHelp , " StackWalk64 " ) ;
pSymGetModuleBase64 = ( fpSymGetModuleBase64 ) : : GetProcAddress ( hLibDbgHelp , " SymGetModuleBase64 " ) ;
pSymGetSymFromAddr64 = ( fpSymGetSymFromAddr64 ) : : GetProcAddress ( hLibDbgHelp , " SymGetSymFromAddr64 " ) ;
pSymGetLineFromAddr64 = ( fpSymGetLineFromAddr64 ) : : GetProcAddress ( hLibDbgHelp , " SymGetLineFromAddr64 " ) ;
pSymFunctionTableAccess64 = ( fpSymFunctionTableAccess64 ) : : GetProcAddress ( hLibDbgHelp , " SymFunctionTableAccess64 " ) ;
pSymInitialize = ( fpSymInitialize ) : : GetProcAddress ( hLibDbgHelp , " SymInitialize " ) ;
pUnDecorateSymbolName = ( fpUnDecorateSymbolName ) : : GetProcAddress ( hLibDbgHelp , " UnDecorateSymbolName " ) ;
2014-06-29 22:53:52 +02:00
return true ;
2014-06-29 18:57:48 +02:00
}
static void PrintCallstack ( FILE * f , PEXCEPTION_POINTERS ex )
{
2014-06-29 22:53:52 +02:00
if ( ! loadDbgHelp ( ) )
return ;
2014-06-29 18:57:48 +02:00
const HANDLE hProcess = GetCurrentProcess ( ) ;
const HANDLE hThread = GetCurrentThread ( ) ;
2014-06-29 22:53:52 +02:00
BOOL result = pSymInitialize (
hProcess ,
0 ,
TRUE
) ;
CONTEXT context = * ( ex - > ContextRecord ) ;
STACKFRAME64 stack = { 0 } ;
2014-06-29 18:57:48 +02:00
# ifdef _M_IX86
stack . AddrPC . Offset = context . Eip ;
stack . AddrPC . Mode = AddrModeFlat ;
stack . AddrStack . Offset = context . Esp ;
stack . AddrStack . Mode = AddrModeFlat ;
stack . AddrFrame . Offset = context . Ebp ;
stack . AddrFrame . Mode = AddrModeFlat ;
# else
2014-06-29 22:53:52 +02:00
stack . AddrPC . Offset = context . Rip ;
2014-06-29 18:57:48 +02:00
stack . AddrPC . Mode = AddrModeFlat ;
stack . AddrStack . Offset = context . Rsp ;
stack . AddrStack . Mode = AddrModeFlat ;
stack . AddrFrame . Offset = context . Rsp ;
stack . AddrFrame . Mode = AddrModeFlat ;
# endif
2014-06-29 22:53:52 +02:00
IMAGEHLP_SYMBOL64_EXT symbol ;
2014-06-30 12:48:42 +02:00
symbol . SizeOfStruct = sizeof ( IMAGEHLP_SYMBOL64 ) ;
symbol . MaxNameLength = maxnamelength ;
2014-06-29 22:53:52 +02:00
DWORD64 displacement = 0 ;
int beyond_main = - 1 ; // emergency exit, see below
for ( ULONG frame = 0 ; ; frame + + ) {
2014-06-29 18:57:48 +02:00
result = pStackWalk64
2014-06-29 22:53:52 +02:00
(
2014-06-29 18:57:48 +02:00
# ifdef _M_IX86
2014-06-29 22:53:52 +02:00
IMAGE_FILE_MACHINE_I386 ,
2014-06-29 18:57:48 +02:00
# else
2014-06-29 22:53:52 +02:00
IMAGE_FILE_MACHINE_AMD64 ,
2014-06-29 18:57:48 +02:00
# endif
2014-06-29 22:53:52 +02:00
hProcess ,
hThread ,
& stack ,
& context ,
NULL ,
pSymFunctionTableAccess64 ,
pSymGetModuleBase64 ,
NULL
) ;
if ( ! result ) // official end...
break ;
2014-07-07 21:25:30 +02:00
pSymGetSymFromAddr64 ( hProcess , ( ULONG64 ) stack . AddrPC . Offset , & displacement , & symbol ) ;
2014-06-29 22:53:52 +02:00
TCHAR undname [ maxnamelength ] = { 0 } ;
2014-06-30 12:48:42 +02:00
pUnDecorateSymbolName ( ( const TCHAR * ) symbol . Name , ( PTSTR ) undname , ( DWORD ) GetArrayLength ( undname ) , UNDNAME_COMPLETE ) ;
2014-06-29 22:53:52 +02:00
if ( beyond_main > = 0 )
+ + beyond_main ;
if ( _tcscmp ( undname , _T ( " main " ) ) = = 0 )
beyond_main = 0 ;
fprintf ( f ,
2014-08-30 13:33:19 +02:00
" %lu. 0x%08I64X in " ,
2014-06-29 22:53:52 +02:00
frame , ( ULONG64 ) stack . AddrPC . Offset ) ;
fputs ( ( const char * ) undname , f ) ;
fputs ( " \n " , f ) ;
if ( 0 = = stack . AddrReturn . Offset | | beyond_main > 2 ) // StackWalk64() sometimes doesn't reach any end...
break ;
2014-06-29 18:57:48 +02:00
}
2014-07-07 21:25:30 +02:00
2014-07-08 06:44:57 +02:00
FreeLibrary ( hLibDbgHelp ) ;
hLibDbgHelp = 0 ;
2014-06-29 18:57:48 +02:00
}
2015-02-20 08:26:02 +01:00
static void writeMemoryErrorDetails ( FILE * f , PEXCEPTION_POINTERS ex , const char * description )
{
fputs ( description , f ) ;
2015-03-24 15:59:24 +01:00
// Using %p for ULONG_PTR later on, so it must have size identical to size of pointer
// This is not the universally portable solution but good enough for Win32/64
C_ASSERT ( sizeof ( void * ) = = sizeof ( ex - > ExceptionRecord - > ExceptionInformation [ 1 ] ) ) ;
2015-02-20 08:26:02 +01:00
switch ( ex - > ExceptionRecord - > ExceptionInformation [ 0 ] ) {
case 0 :
2015-03-24 15:59:24 +01:00
fprintf ( f , " reading from 0x%p " ,
2015-02-20 08:26:02 +01:00
ex - > ExceptionRecord - > ExceptionInformation [ 1 ] ) ;
break ;
case 1 :
2015-03-24 15:59:24 +01:00
fprintf ( f , " writing at 0x%p " ,
2015-02-20 08:26:02 +01:00
ex - > ExceptionRecord - > ExceptionInformation [ 1 ] ) ;
break ;
case 8 :
2015-03-24 15:59:24 +01:00
fprintf ( f , " data execution prevention at 0x%p " ,
2015-02-20 08:26:02 +01:00
ex - > ExceptionRecord - > ExceptionInformation [ 1 ] ) ;
break ;
default :
break ;
}
}
2014-03-16 18:37:28 +01:00
/*
2015-03-08 14:24:54 +01:00
* Any evaluation of the exception needs to be done here !
2014-03-16 18:37:28 +01:00
*/
static int filterException ( int code , PEXCEPTION_POINTERS ex )
{
2014-05-25 08:47:37 +02:00
FILE * f = stdout ;
2014-06-28 14:05:18 +02:00
fputs ( " Internal error: " , f ) ;
2014-03-17 19:11:00 +01:00
switch ( ex - > ExceptionRecord - > ExceptionCode ) {
case EXCEPTION_ACCESS_VIOLATION :
2015-02-20 08:26:02 +01:00
writeMemoryErrorDetails ( f , ex , " Access violation " ) ;
2014-06-28 14:05:18 +02:00
break ;
2014-06-28 12:14:00 +02:00
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED :
fputs ( " Out of array bounds " , f ) ;
2014-06-28 14:05:18 +02:00
break ;
2014-06-28 12:14:00 +02:00
case EXCEPTION_BREAKPOINT :
fputs ( " Breakpoint " , f ) ;
2014-06-28 14:05:18 +02:00
break ;
2014-06-28 12:14:00 +02:00
case EXCEPTION_DATATYPE_MISALIGNMENT :
fputs ( " Misaligned data " , f ) ;
2014-06-28 14:05:18 +02:00
break ;
2014-06-28 12:14:00 +02:00
case EXCEPTION_FLT_DENORMAL_OPERAND :
fputs ( " Denormalized floating-point value " , f ) ;
2014-06-28 14:05:18 +02:00
break ;
2014-06-28 12:14:00 +02:00
case EXCEPTION_FLT_DIVIDE_BY_ZERO :
fputs ( " Floating-point divide-by-zero " , f ) ;
2014-06-28 14:05:18 +02:00
break ;
2014-06-28 12:14:00 +02:00
case EXCEPTION_FLT_INEXACT_RESULT :
fputs ( " Inexact floating-point value " , f ) ;
2014-06-28 14:05:18 +02:00
break ;
2014-06-28 12:14:00 +02:00
case EXCEPTION_FLT_INVALID_OPERATION :
fputs ( " Invalid floating-point operation " , f ) ;
2014-06-28 14:05:18 +02:00
break ;
2014-06-28 12:14:00 +02:00
case EXCEPTION_FLT_OVERFLOW :
fputs ( " Floating-point overflow " , f ) ;
2014-06-28 14:05:18 +02:00
break ;
2014-06-28 12:14:00 +02:00
case EXCEPTION_FLT_STACK_CHECK :
fputs ( " Floating-point stack overflow " , f ) ;
2014-06-28 14:05:18 +02:00
break ;
2014-06-28 12:14:00 +02:00
case EXCEPTION_FLT_UNDERFLOW :
fputs ( " Floating-point underflow " , f ) ;
2014-06-28 14:05:18 +02:00
break ;
2014-06-28 12:14:00 +02:00
case EXCEPTION_GUARD_PAGE :
fputs ( " Page-guard access " , f ) ;
2014-06-28 14:05:18 +02:00
break ;
2014-06-28 12:14:00 +02:00
case EXCEPTION_ILLEGAL_INSTRUCTION :
fputs ( " Illegal instruction " , f ) ;
2014-06-28 14:05:18 +02:00
break ;
2014-03-17 19:11:00 +01:00
case EXCEPTION_IN_PAGE_ERROR :
2015-02-20 08:26:02 +01:00
writeMemoryErrorDetails ( f , ex , " Invalid page access " ) ;
2014-06-28 14:05:18 +02:00
break ;
2014-06-28 12:14:00 +02:00
case EXCEPTION_INT_DIVIDE_BY_ZERO :
fputs ( " Integer divide-by-zero " , f ) ;
2014-06-28 14:05:18 +02:00
break ;
2014-06-28 12:14:00 +02:00
case EXCEPTION_INT_OVERFLOW :
fputs ( " Integer overflow " , f ) ;
2014-06-28 14:05:18 +02:00
break ;
2014-06-28 12:14:00 +02:00
case EXCEPTION_INVALID_DISPOSITION :
fputs ( " Invalid exception dispatcher " , f ) ;
2014-06-28 14:05:18 +02:00
break ;
2014-06-28 12:14:00 +02:00
case EXCEPTION_INVALID_HANDLE :
fputs ( " Invalid handle " , f ) ;
2014-06-28 14:05:18 +02:00
break ;
2014-06-28 12:14:00 +02:00
case EXCEPTION_NONCONTINUABLE_EXCEPTION :
fputs ( " Non-continuable exception " , f ) ;
2014-06-28 14:05:18 +02:00
break ;
2014-06-28 12:14:00 +02:00
case EXCEPTION_PRIV_INSTRUCTION :
fputs ( " Invalid instruction " , f ) ;
2014-06-28 14:05:18 +02:00
break ;
2014-06-28 12:14:00 +02:00
case EXCEPTION_SINGLE_STEP :
fputs ( " Single instruction step " , f ) ;
2014-06-28 14:05:18 +02:00
break ;
2014-06-28 12:14:00 +02:00
case EXCEPTION_STACK_OVERFLOW :
fputs ( " Stack overflow " , f ) ;
2014-06-28 14:05:18 +02:00
break ;
2014-03-17 19:11:00 +01:00
default :
2014-06-28 12:14:00 +02:00
fprintf ( f , " Unknown exception (%d) \n " ,
2014-03-17 19:11:00 +01:00
code ) ;
break ;
}
2014-06-28 14:05:18 +02:00
fputs ( " \n " , f ) ;
2014-06-29 22:53:52 +02:00
PrintCallstack ( f , ex ) ;
2015-04-01 21:17:13 +02:00
fflush ( f ) ;
2014-03-16 18:37:28 +01:00
return EXCEPTION_EXECUTE_HANDLER ;
}
# endif
/**
* Signal / SEH handling
2014-03-18 21:14:09 +01:00
* Has to be clean for using with SEH on windows , i . e . no construction of C + + object instances is allowed !
2014-03-16 18:37:28 +01:00
* TODO Check for multi - threading issues !
*
*/
2014-04-07 20:39:19 +02:00
int CppCheckExecutor : : check_wrapper ( CppCheck & cppcheck , int argc , const char * const argv [ ] )
2014-03-16 12:04:13 +01:00
{
2014-03-17 19:11:00 +01:00
# ifdef USE_WINDOWS_SEH
2014-05-25 08:47:37 +02:00
FILE * f = stdout ;
2014-03-17 19:11:00 +01:00
__try {
2014-04-07 20:39:19 +02:00
return check_internal ( cppcheck , argc , argv ) ;
2014-03-17 19:11:00 +01:00
} __except ( filterException ( GetExceptionCode ( ) , GetExceptionInformation ( ) ) ) {
2015-03-08 14:24:54 +01:00
// reporting to stdout may not be helpful within a GUI application...
2014-06-28 12:14:00 +02:00
fputs ( " Please report this to the cppcheck developers! \n " , f ) ;
2014-03-16 18:37:28 +01:00
return - 1 ;
}
2014-06-28 14:05:18 +02:00
# elif defined(USE_UNIX_SIGNAL_HANDLING)
2015-03-07 20:47:27 +01:00
// determine stack vs. heap
char stackVariable ;
char * heapVariable = ( char * ) malloc ( 1 ) ;
bStackBelowHeap = & stackVariable < heapVariable ;
free ( heapVariable ) ;
// set up alternative stack for signal handler
2015-03-07 18:15:25 +01:00
stack_t segv_stack ;
segv_stack . ss_sp = mytstack ;
segv_stack . ss_flags = 0 ;
segv_stack . ss_size = MYSTACKSIZE ;
sigaltstack ( & segv_stack , NULL ) ;
2015-03-07 20:47:27 +01:00
// install signal handler
2014-03-16 18:37:28 +01:00
struct sigaction act ;
memset ( & act , 0 , sizeof ( act ) ) ;
2015-03-07 18:15:25 +01:00
act . sa_flags = SA_SIGINFO | SA_ONSTACK ;
2014-03-16 18:37:28 +01:00
act . sa_sigaction = CppcheckSignalHandler ;
for ( std : : size_t s = 0 ; s < GetArrayLength ( listofsignals ) ; + + s ) {
sigaction ( listofsignals [ s ] . signalnumber , & act , NULL ) ;
2014-03-16 12:04:13 +01:00
}
2014-04-07 20:39:19 +02:00
return check_internal ( cppcheck , argc , argv ) ;
2014-03-16 12:04:13 +01:00
# else
2014-04-07 20:39:19 +02:00
return check_internal ( cppcheck , argc , argv ) ;
2014-03-16 12:04:13 +01:00
# endif
}
2014-03-18 21:14:09 +01:00
/*
* That is a method which gets called from check_wrapper
* */
2014-04-07 20:39:19 +02:00
int CppCheckExecutor : : check_internal ( CppCheck & cppcheck , int /*argc*/ , const char * const argv [ ] )
2014-03-16 12:04:13 +01:00
{
2014-04-07 20:39:19 +02:00
Settings & settings = cppcheck . settings ( ) ;
2014-03-16 12:04:13 +01:00
_settings = & settings ;
2015-01-10 22:18:57 +01:00
bool std = tryLoadLibrary ( settings . library , argv [ 0 ] , " std.cfg " ) ;
2013-12-26 11:15:28 +01:00
bool posix = true ;
2013-12-23 10:06:45 +01:00
if ( settings . standards . posix )
2015-01-10 22:18:57 +01:00
posix = tryLoadLibrary ( settings . library , argv [ 0 ] , " posix.cfg " ) ;
2014-10-19 07:34:40 +02:00
bool windows = true ;
if ( settings . isWindowsPlatform ( ) )
2015-01-10 22:18:57 +01:00
windows = tryLoadLibrary ( settings . library , argv [ 0 ] , " windows.cfg " ) ;
2013-12-26 11:15:28 +01:00
2014-10-19 07:34:40 +02:00
if ( ! std | | ! posix | | ! windows ) {
2013-12-26 11:15:28 +01:00
const std : : list < ErrorLogger : : ErrorMessage : : FileLocation > callstack ;
2014-10-19 07:34:40 +02:00
const std : : string msg ( " Failed to load " + std : : string ( ! std ? " std.cfg " : ! posix ? " posix.cfg " : " windows.cfg " ) + " . Your Cppcheck installation is broken, please re-install. " ) ;
2014-01-03 21:59:50 +01:00
# ifdef CFGDIR
const std : : string details ( " The Cppcheck binary was compiled with CFGDIR set to \" " +
std : : string ( CFGDIR ) + " \" and will therefore search for "
" std.cfg in that path. " ) ;
# else
const std : : string cfgfolder ( Path : : fromNativeSeparators ( Path : : getPathFromFilename ( argv [ 0 ] ) ) + " cfg " ) ;
const std : : string details ( " The Cppcheck binary was compiled without CFGDIR set. Either the "
" std.cfg should be available in " + cfgfolder + " or the CFGDIR "
" should be configured. " ) ;
# endif
ErrorLogger : : ErrorMessage errmsg ( callstack , Severity : : information , msg + " " + details , " failedToLoadCfg " , false ) ;
2013-12-26 11:15:28 +01:00
reportErr ( errmsg ) ;
return EXIT_FAILURE ;
}
2013-12-23 10:06:45 +01:00
2012-04-06 14:19:26 +02:00
if ( settings . reportProgress )
2010-08-12 21:03:33 +02:00
time1 = std : : time ( 0 ) ;
2012-04-06 14:19:26 +02:00
if ( settings . _xml ) {
reportErr ( ErrorLogger : : ErrorMessage : : getXMLHeader ( settings . _xml_version ) ) ;
2009-10-17 08:19:37 +02:00
}
2009-02-09 21:51:04 +01:00
2009-10-17 08:19:37 +02:00
unsigned int returnValue = 0 ;
2012-04-06 14:19:26 +02:00
if ( settings . _jobs = = 1 ) {
2009-10-17 08:19:37 +02:00
// Single process
2015-01-07 19:26:16 +01:00
settings . jointSuppressionReport = true ;
2011-04-19 13:52:32 +02:00
2012-07-08 23:39:46 +02:00
std : : size_t totalfilesize = 0 ;
for ( std : : map < std : : string , std : : size_t > : : const_iterator i = _files . begin ( ) ; i ! = _files . end ( ) ; + + i ) {
2011-04-19 13:52:32 +02:00
totalfilesize + = i - > second ;
}
2012-07-08 23:39:46 +02:00
std : : size_t processedsize = 0 ;
2012-02-19 17:22:59 +01:00
unsigned int c = 0 ;
2012-07-08 23:39:46 +02:00
for ( std : : map < std : : string , std : : size_t > : : const_iterator i = _files . begin ( ) ; i ! = _files . end ( ) ; + + i ) {
2014-01-02 18:18:24 +01:00
if ( ! _settings - > library . markupFile ( i - > first )
2014-01-02 21:47:35 +01:00
| | ! _settings - > library . processMarkupAfterCode ( i - > first ) ) {
2014-04-07 20:39:19 +02:00
returnValue + = cppcheck . check ( i - > first ) ;
2013-10-20 14:09:10 +02:00
processedsize + = i - > second ;
if ( ! settings . _errorsOnly )
reportStatus ( c + 1 , _files . size ( ) , processedsize , totalfilesize ) ;
c + + ;
}
}
2013-10-31 19:09:01 +01:00
// second loop to parse all markup files which may not work until all
2013-10-20 14:09:10 +02:00
// c/cpp files have been parsed and checked
for ( std : : map < std : : string , std : : size_t > : : const_iterator i = _files . begin ( ) ; i ! = _files . end ( ) ; + + i ) {
2014-01-02 18:18:24 +01:00
if ( _settings - > library . markupFile ( i - > first ) & & _settings - > library . processMarkupAfterCode ( i - > first ) ) {
2014-04-07 20:39:19 +02:00
returnValue + = cppcheck . check ( i - > first ) ;
2013-10-20 14:09:10 +02:00
processedsize + = i - > second ;
if ( ! settings . _errorsOnly )
reportStatus ( c + 1 , _files . size ( ) , processedsize , totalfilesize ) ;
c + + ;
}
2011-04-23 14:20:55 +02:00
}
2014-11-15 10:43:49 +01:00
cppcheck . analyseWholeProgram ( ) ;
2011-10-13 20:53:06 +02:00
} else if ( ! ThreadExecutor : : isEnabled ( ) ) {
2009-10-17 08:19:37 +02:00
std : : cout < < " No thread support yet implemented for this platform. " < < std : : endl ;
2011-10-13 20:53:06 +02:00
} else {
2009-10-17 08:19:37 +02:00
// Multiple processes
2012-02-19 17:22:59 +01:00
ThreadExecutor executor ( _files , settings , * this ) ;
2009-10-17 08:19:37 +02:00
returnValue = executor . check ( ) ;
2009-01-08 22:30:25 +01:00
}
2009-10-17 08:19:37 +02:00
2015-01-07 19:26:16 +01:00
if ( settings . isEnabled ( " information " ) | | settings . checkConfiguration ) {
const bool enableUnusedFunctionCheck = cppcheck . unusedFunctionCheckIsEnabled ( ) ;
if ( settings . jointSuppressionReport ) {
for ( std : : map < std : : string , std : : size_t > : : const_iterator i = _files . begin ( ) ; i ! = _files . end ( ) ; + + i ) {
reportUnmatchedSuppressions ( settings . nomsg . getUnmatchedLocalSuppressions ( i - > first , enableUnusedFunctionCheck ) ) ;
}
}
reportUnmatchedSuppressions ( settings . nomsg . getUnmatchedGlobalSuppressions ( enableUnusedFunctionCheck ) ) ;
}
2011-05-02 14:58:16 +02:00
2013-05-31 15:20:58 +02:00
if ( ! settings . checkConfiguration ) {
2014-04-07 20:39:19 +02:00
cppcheck . tooManyConfigsError ( " " , 0U ) ;
2012-12-26 18:35:49 +01:00
2014-05-03 19:31:15 +02:00
if ( settings . isEnabled ( " missingInclude " ) & & ( Preprocessor : : missingIncludeFlag | | Preprocessor : : missingSystemIncludeFlag ) ) {
2011-05-02 14:58:16 +02:00
const std : : list < ErrorLogger : : ErrorMessage : : FileLocation > callStack ;
ErrorLogger : : ErrorMessage msg ( callStack ,
Severity : : information ,
2011-05-04 18:52:03 +02:00
" Cppcheck cannot find all the include files (use --check-config for details) \n "
2011-11-05 17:56:40 +01:00
" Cppcheck cannot find all the include files. Cppcheck can check the code without the "
2011-05-02 14:58:16 +02:00
" include files found. But the results will probably be more accurate if all the include "
" files are found. Please check your project's include directories and add all of them "
" as include directories for Cppcheck. To see what files Cppcheck cannot find use "
2011-05-04 18:52:03 +02:00
" --check-config. " ,
2014-05-03 19:31:15 +02:00
Preprocessor : : missingIncludeFlag ? " missingInclude " : " missingIncludeSystem " ,
2011-05-02 14:58:16 +02:00
false ) ;
2012-06-18 23:15:48 +02:00
reportInfo ( msg ) ;
2011-05-02 14:58:16 +02:00
}
}
2011-02-16 02:12:15 +01:00
2012-04-06 14:19:26 +02:00
if ( settings . _xml ) {
reportErr ( ErrorLogger : : ErrorMessage : : getXMLFooter ( settings . _xml_version ) ) ;
2009-10-17 08:19:37 +02:00
}
2012-04-06 14:19:26 +02:00
_settings = 0 ;
2010-04-02 07:30:58 +02:00
if ( returnValue )
2012-04-06 14:19:26 +02:00
return settings . _exitCode ;
2009-10-17 08:19:37 +02:00
else
return 0 ;
2008-12-18 22:28:57 +01:00
}
2009-01-05 16:49:57 +01:00
void CppCheckExecutor : : reportErr ( const std : : string & errmsg )
2008-12-18 22:28:57 +01:00
{
2011-10-09 20:03:38 +02:00
// Alert only about unique errors
2012-02-19 17:22:59 +01:00
if ( _errorList . find ( errmsg ) ! = _errorList . end ( ) )
2011-10-09 20:03:38 +02:00
return ;
2012-02-19 17:22:59 +01:00
_errorList . insert ( errmsg ) ;
2008-12-18 22:28:57 +01:00
std : : cerr < < errmsg < < std : : endl ;
}
2009-01-05 16:49:57 +01:00
void CppCheckExecutor : : reportOut ( const std : : string & outmsg )
2008-12-18 22:28:57 +01:00
{
std : : cout < < outmsg < < std : : endl ;
}
2009-02-01 19:00:47 +01:00
2012-07-08 23:39:46 +02:00
void CppCheckExecutor : : reportProgress ( const std : : string & filename , const char stage [ ] , const std : : size_t value )
2010-08-08 08:45:37 +02:00
{
( void ) filename ;
2012-01-02 07:42:39 +01:00
if ( ! time1 )
2010-08-12 21:03:33 +02:00
return ;
2010-08-08 08:45:37 +02:00
// Report progress messages every 10 seconds
const std : : time_t time2 = std : : time ( NULL ) ;
2012-01-02 07:42:39 +01:00
if ( time2 > = ( time1 + 10 ) ) {
2010-08-08 08:45:37 +02:00
time1 = time2 ;
// format a progress message
std : : ostringstream ostr ;
ostr < < " progress: "
< < stage
2012-07-06 13:17:08 +02:00
< < ' ' < < value < < ' % ' ;
2010-08-08 08:45:37 +02:00
// Report progress message
reportOut ( ostr . str ( ) ) ;
}
}
2012-06-18 23:15:48 +02:00
void CppCheckExecutor : : reportInfo ( const ErrorLogger : : ErrorMessage & msg )
{
2012-07-04 18:21:56 +02:00
reportErr ( msg ) ;
2012-06-18 23:15:48 +02:00
}
2012-07-08 23:39:46 +02:00
void CppCheckExecutor : : reportStatus ( std : : size_t fileindex , std : : size_t filecount , std : : size_t sizedone , std : : size_t sizetotal )
2009-02-19 23:21:18 +01:00
{
2011-10-13 20:53:06 +02:00
if ( filecount > 1 ) {
2009-02-19 23:21:18 +01:00
std : : ostringstream oss ;
2012-02-18 11:55:05 +01:00
oss < < fileindex < < ' / ' < < filecount
2010-04-15 20:08:51 +02:00
< < " files checked " < <
2011-11-01 13:07:45 +01:00
( sizetotal > 0 ? static_cast < long > ( static_cast < long double > ( sizedone ) / sizetotal * 100 ) : 0 )
2010-04-15 20:08:51 +02:00
< < " % done " ;
2009-02-19 23:21:18 +01:00
std : : cout < < oss . str ( ) < < std : : endl ;
}
}
2009-02-10 22:51:52 +01:00
void CppCheckExecutor : : reportErr ( const ErrorLogger : : ErrorMessage & msg )
2009-02-01 19:00:47 +01:00
{
2011-10-13 20:53:06 +02:00
if ( errorlist ) {
2012-04-06 14:19:26 +02:00
reportOut ( msg . toXML ( false , _settings - > _xml_version ) ) ;
} else if ( _settings - > _xml ) {
reportErr ( msg . toXML ( _settings - > _verbose , _settings - > _xml_version ) ) ;
2011-10-13 20:53:06 +02:00
} else {
2012-04-06 14:19:26 +02:00
reportErr ( msg . toString ( _settings - > _verbose , _settings - > _outputFormat ) ) ;
2009-02-09 21:51:04 +01:00
}
2009-02-01 19:00:47 +01:00
}
2014-05-25 08:47:37 +02:00
void CppCheckExecutor : : setExceptionOutput ( const std : : string & fn )
{
exceptionOutput = fn ;
}
2014-05-25 15:53:26 +02:00
2014-05-25 08:47:37 +02:00
const std : : string & CppCheckExecutor : : getExceptionOutput ( )
{
return exceptionOutput ;
}
2014-05-25 15:53:26 +02:00
2015-01-10 22:18:57 +01:00
bool CppCheckExecutor : : tryLoadLibrary ( Library & destination , const char * basepath , const char * filename )
{
2015-03-07 20:47:27 +01:00
const Library : : Error err = destination . load ( basepath , filename ) ;
2015-01-10 22:18:57 +01:00
if ( err . errorcode = = Library : : UNKNOWN_ELEMENT )
std : : cout < < " cppcheck: Found unknown elements in configuration file ' " < < filename < < " ': " < < err . reason < < std : : endl ;
else if ( err . errorcode ! = Library : : OK ) {
std : : string errmsg ;
switch ( err . errorcode ) {
case Library : : OK :
break ;
case Library : : FILE_NOT_FOUND :
errmsg = " File not found " ;
break ;
case Library : : BAD_XML :
errmsg = " Bad XML " ;
break ;
case Library : : UNKNOWN_ELEMENT :
errmsg = " Unexpected element " ;
break ;
case Library : : MISSING_ATTRIBUTE :
errmsg = " Missing attribute " ;
break ;
case Library : : BAD_ATTRIBUTE_VALUE :
errmsg = " Bad attribute value " ;
break ;
case Library : : UNSUPPORTED_FORMAT :
errmsg = " File is of unsupported format version " ;
break ;
case Library : : DUPLICATE_PLATFORM_TYPE :
errmsg = " Duplicate platform type " ;
break ;
case Library : : PLATFORM_TYPE_REDEFINED :
errmsg = " Platform type redefined " ;
break ;
}
if ( ! err . reason . empty ( ) )
errmsg + = " ' " + err . reason + " ' " ;
std : : cout < < " cppcheck: Failed to load library configuration file ' " < < filename < < " '. " < < errmsg < < std : : endl ;
return false ;
}
return true ;
}
2014-05-25 08:47:37 +02:00
std : : string CppCheckExecutor : : exceptionOutput ;