2009-01-09 20:01:25 +01:00
/*
2009-01-21 21:04:20 +01:00
* Cppcheck - A tool for static C / C + + code analysis
2018-03-31 20:59:09 +02:00
* Copyright ( C ) 2007 - 2018 Cppcheck team .
2009-01-09 20:01:25 +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/>.
2009-01-09 20:01:25 +01:00
*/
2009-02-01 16:47:36 +01:00
# include "errorlogger.h"
2017-05-27 04:33:47 +02:00
2010-12-22 10:29:23 +01:00
# include "cppcheck.h"
2017-05-27 04:33:47 +02:00
# include "mathlib.h"
# include "path.h"
2013-05-07 18:18:15 +02:00
# include "token.h"
2017-05-27 04:33:47 +02:00
# include "tokenlist.h"
2016-02-27 16:03:50 +01:00
# include "utils.h"
2009-01-03 14:51:55 +01:00
2013-08-07 16:30:55 +02:00
# include <tinyxml2.h>
2017-05-27 04:33:47 +02:00
# include <array>
2011-12-30 00:22:16 +01:00
# include <cassert>
2017-05-27 04:33:47 +02:00
# include <cctype>
# include <cstdlib>
# include <cstring>
2014-04-13 09:50:57 +02:00
# include <iomanip>
2009-02-01 16:47:36 +01:00
2014-03-27 13:15:21 +01:00
InternalError : : InternalError ( const Token * tok , const std : : string & errorMsg , Type type ) :
2018-11-13 20:14:56 +01:00
token ( tok ) , errorMessage ( errorMsg ) , type ( type )
2012-01-08 21:19:44 +01:00
{
2014-03-27 13:15:21 +01:00
switch ( type ) {
2017-09-05 16:56:13 +02:00
case AST :
id = " internalAstError " ;
break ;
2014-03-27 13:15:21 +01:00
case SYNTAX :
id = " syntaxError " ;
break ;
2018-11-13 20:14:56 +01:00
case UNKNOWN_MACRO :
id = " unknownMacro " ;
break ;
2014-03-27 13:15:21 +01:00
case INTERNAL :
id = " cppcheckError " ;
break ;
}
2012-01-08 21:19:44 +01:00
}
2009-02-19 23:21:18 +01:00
ErrorLogger : : ErrorMessage : : ErrorMessage ( )
2015-04-25 17:48:11 +02:00
: _severity ( Severity : : none ) , _cwe ( 0U ) , _inconclusive ( false )
2009-02-19 23:21:18 +01:00
{
}
2010-07-27 09:32:20 +02:00
lib: fix a bunch of warnings about differing function arguments in definition and declaration.
[lib/token.h:72] -> [lib/token.cpp:36]: (style, inconclusive) Function 'Token' argument 1 names different: declaration 'tokensBack' definition 't'.
[lib/token.h:445] -> [lib/token.cpp:497]: (style, inconclusive) Function 'multiCompare' argument 1 names different: declaration 'needle' definition 'tok'.
[lib/checkio.h:73] -> [lib/checkio.cpp:1385]: (style, inconclusive) Function 'ArgumentInfo' argument 3 names different: declaration 'isCPP' definition '_isCPP'.
[lib/checkother.h:216] -> [lib/checkother.cpp:2136]: (style, inconclusive) Function 'checkComparisonFunctionIsAlwaysTrueOrFalseError' argument 2 names different: declaration 'strFunctionName' definition 'functionName'.
[lib/errorlogger.h:214] -> [lib/errorlogger.cpp:51]: (style, inconclusive) Function 'ErrorMessage' argument 2 names different: declaration 'file0' definition 'file0_'.
[lib/errorlogger.h:215] -> [lib/errorlogger.cpp:65]: (style, inconclusive) Function 'ErrorMessage' argument 2 names different: declaration 'file0' definition 'file0_'.
[lib/library.h:327] -> [lib/library.cpp:1043]: (style, inconclusive) Function 'ignorefunction' argument 1 names different: declaration 'function' definition 'functionName'.
[lib/mathlib.h:112] -> [lib/mathlib.cpp:1275]: (style, inconclusive) Function 'isNullValue' argument 1 names different: declaration 'tok' definition 'str'.
[lib/preprocessor.h:91] -> [lib/preprocessor.cpp:122]: (style, inconclusive) Function 'setDirectives' argument 1 names different: declaration 'tokens' definition 'tokens1'.
[lib/symboldatabase.h:860] -> [lib/symboldatabase.cpp:1801]: (style, inconclusive) Function 'argsMatch' argument 1 names different: declaration 'info' definition 'scope'.
[lib/symboldatabase.h:1171] -> [lib/symboldatabase.cpp:2048]: (style, inconclusive) Function 'addClassFunction' argument 1 names different: declaration 'info' definition 'scope'.
[lib/symboldatabase.h:1174] -> [lib/symboldatabase.cpp:2208]: (style, inconclusive) Function 'addNewFunction' argument 1 names different: declaration 'info' definition 'scope'.
[lib/symboldatabase.h:1090] -> [lib/symboldatabase.cpp:3648]: (style, inconclusive) Function 'findVariableType' argument 2 names different: declaration 'type' definition 'typeTok'.
[lib/symboldatabase.h:1101] -> [lib/symboldatabase.cpp:4308]: (style, inconclusive) Function 'findType' argument 1 names different: declaration 'tok' definition 'startTok'.
[lib/symboldatabase.h:1176] -> [lib/symboldatabase.cpp:4349]: (style, inconclusive) Function 'findTypeInNested' argument 1 names different: declaration 'tok' definition 'startTok'.
[lib/symboldatabase.h:1193] -> [lib/symboldatabase.cpp:4501]: (style, inconclusive) Function 'setValueType' argument 2 names different: declaration 'enumerators' definition 'enumerator'.
[lib/path.h:159] -> [lib/path.cpp:247]: (style, inconclusive) Function 'isCPP' argument 1 names different: declaration 'extensionInLowerCase' definition 'path'.
[lib/path.h:145] -> [lib/path.cpp:266]: (style, inconclusive) Function 'acceptFile' argument 1 names different: declaration 'filename' definition 'path'.
2017-04-03 00:06:46 +02:00
ErrorLogger : : ErrorMessage : : ErrorMessage ( const std : : list < FileLocation > & callStack , const std : : string & file1 , Severity : : SeverityType severity , const std : : string & msg , const std : : string & id , bool inconclusive ) :
2012-04-06 18:16:59 +02:00
_callStack ( callStack ) , // locations for this error message
_id ( id ) , // set the message id
lib: fix a bunch of warnings about differing function arguments in definition and declaration.
[lib/token.h:72] -> [lib/token.cpp:36]: (style, inconclusive) Function 'Token' argument 1 names different: declaration 'tokensBack' definition 't'.
[lib/token.h:445] -> [lib/token.cpp:497]: (style, inconclusive) Function 'multiCompare' argument 1 names different: declaration 'needle' definition 'tok'.
[lib/checkio.h:73] -> [lib/checkio.cpp:1385]: (style, inconclusive) Function 'ArgumentInfo' argument 3 names different: declaration 'isCPP' definition '_isCPP'.
[lib/checkother.h:216] -> [lib/checkother.cpp:2136]: (style, inconclusive) Function 'checkComparisonFunctionIsAlwaysTrueOrFalseError' argument 2 names different: declaration 'strFunctionName' definition 'functionName'.
[lib/errorlogger.h:214] -> [lib/errorlogger.cpp:51]: (style, inconclusive) Function 'ErrorMessage' argument 2 names different: declaration 'file0' definition 'file0_'.
[lib/errorlogger.h:215] -> [lib/errorlogger.cpp:65]: (style, inconclusive) Function 'ErrorMessage' argument 2 names different: declaration 'file0' definition 'file0_'.
[lib/library.h:327] -> [lib/library.cpp:1043]: (style, inconclusive) Function 'ignorefunction' argument 1 names different: declaration 'function' definition 'functionName'.
[lib/mathlib.h:112] -> [lib/mathlib.cpp:1275]: (style, inconclusive) Function 'isNullValue' argument 1 names different: declaration 'tok' definition 'str'.
[lib/preprocessor.h:91] -> [lib/preprocessor.cpp:122]: (style, inconclusive) Function 'setDirectives' argument 1 names different: declaration 'tokens' definition 'tokens1'.
[lib/symboldatabase.h:860] -> [lib/symboldatabase.cpp:1801]: (style, inconclusive) Function 'argsMatch' argument 1 names different: declaration 'info' definition 'scope'.
[lib/symboldatabase.h:1171] -> [lib/symboldatabase.cpp:2048]: (style, inconclusive) Function 'addClassFunction' argument 1 names different: declaration 'info' definition 'scope'.
[lib/symboldatabase.h:1174] -> [lib/symboldatabase.cpp:2208]: (style, inconclusive) Function 'addNewFunction' argument 1 names different: declaration 'info' definition 'scope'.
[lib/symboldatabase.h:1090] -> [lib/symboldatabase.cpp:3648]: (style, inconclusive) Function 'findVariableType' argument 2 names different: declaration 'type' definition 'typeTok'.
[lib/symboldatabase.h:1101] -> [lib/symboldatabase.cpp:4308]: (style, inconclusive) Function 'findType' argument 1 names different: declaration 'tok' definition 'startTok'.
[lib/symboldatabase.h:1176] -> [lib/symboldatabase.cpp:4349]: (style, inconclusive) Function 'findTypeInNested' argument 1 names different: declaration 'tok' definition 'startTok'.
[lib/symboldatabase.h:1193] -> [lib/symboldatabase.cpp:4501]: (style, inconclusive) Function 'setValueType' argument 2 names different: declaration 'enumerators' definition 'enumerator'.
[lib/path.h:159] -> [lib/path.cpp:247]: (style, inconclusive) Function 'isCPP' argument 1 names different: declaration 'extensionInLowerCase' definition 'path'.
[lib/path.h:145] -> [lib/path.cpp:266]: (style, inconclusive) Function 'acceptFile' argument 1 names different: declaration 'filename' definition 'path'.
2017-04-03 00:06:46 +02:00
file0 ( file1 ) ,
2012-05-14 20:46:23 +02:00
_severity ( severity ) , // severity for this error message
2015-04-25 17:48:11 +02:00
_cwe ( 0U ) ,
2012-04-06 18:16:59 +02:00
_inconclusive ( inconclusive )
2009-02-10 22:51:52 +01:00
{
2010-12-30 22:07:27 +01:00
// set the summary and verbose messages
2010-11-11 19:54:43 +01:00
setmsg ( msg ) ;
2009-02-10 22:51:52 +01:00
}
Mapped toomanyconfigs ,AssignmentAddressToInteger
,AssignmentIntegerToAddress ,CastIntegerToAddressAtReturn
,CastAddressToIntegerAtReturn ,assertWithSideEffect ,assignmentInAssert
,uselessAssignmentArg ,uselessAssignmentPtrArg
,comparisonOfFuncReturningBoolError
,comparisonOfTwoFuncsReturningBoolError ,comparisonOfBoolWithBoolError
,incrementboolean ,comparisonOfBoolWithInt ,compareBoolExpressionWithInt
,negativeIndex ,pointerOutOfBounds ,arrayIndexThenCheck
,possibleBufferAccessOutOfBounds ,argumentSize
,arrayIndexOutOfBoundsCond ,noConstructor ,copyCtorPointerCopying
,noCopyConstructor ,uninitMemberVar ,operatorEqVarError
,unusedPrivateFunction ,memsetClassFloat ,mallocOnClassWarning
,operatorEq ,thisSubtraction ,operatorEqRetRefThis ,operatorEqToSelf
,useInitializationList ,duplInheritedMember ,assignIfError
,comparisonError ,multiCondition ,mismatchingBitAnd
,oppositeInnerCondition ,incorrectLogicOperator ,redundantCondition
,moduloAlwaysTrueFalse to their CWEs ids.
2016-02-20 23:56:36 +01:00
lib: fix a bunch of warnings about differing function arguments in definition and declaration.
[lib/token.h:72] -> [lib/token.cpp:36]: (style, inconclusive) Function 'Token' argument 1 names different: declaration 'tokensBack' definition 't'.
[lib/token.h:445] -> [lib/token.cpp:497]: (style, inconclusive) Function 'multiCompare' argument 1 names different: declaration 'needle' definition 'tok'.
[lib/checkio.h:73] -> [lib/checkio.cpp:1385]: (style, inconclusive) Function 'ArgumentInfo' argument 3 names different: declaration 'isCPP' definition '_isCPP'.
[lib/checkother.h:216] -> [lib/checkother.cpp:2136]: (style, inconclusive) Function 'checkComparisonFunctionIsAlwaysTrueOrFalseError' argument 2 names different: declaration 'strFunctionName' definition 'functionName'.
[lib/errorlogger.h:214] -> [lib/errorlogger.cpp:51]: (style, inconclusive) Function 'ErrorMessage' argument 2 names different: declaration 'file0' definition 'file0_'.
[lib/errorlogger.h:215] -> [lib/errorlogger.cpp:65]: (style, inconclusive) Function 'ErrorMessage' argument 2 names different: declaration 'file0' definition 'file0_'.
[lib/library.h:327] -> [lib/library.cpp:1043]: (style, inconclusive) Function 'ignorefunction' argument 1 names different: declaration 'function' definition 'functionName'.
[lib/mathlib.h:112] -> [lib/mathlib.cpp:1275]: (style, inconclusive) Function 'isNullValue' argument 1 names different: declaration 'tok' definition 'str'.
[lib/preprocessor.h:91] -> [lib/preprocessor.cpp:122]: (style, inconclusive) Function 'setDirectives' argument 1 names different: declaration 'tokens' definition 'tokens1'.
[lib/symboldatabase.h:860] -> [lib/symboldatabase.cpp:1801]: (style, inconclusive) Function 'argsMatch' argument 1 names different: declaration 'info' definition 'scope'.
[lib/symboldatabase.h:1171] -> [lib/symboldatabase.cpp:2048]: (style, inconclusive) Function 'addClassFunction' argument 1 names different: declaration 'info' definition 'scope'.
[lib/symboldatabase.h:1174] -> [lib/symboldatabase.cpp:2208]: (style, inconclusive) Function 'addNewFunction' argument 1 names different: declaration 'info' definition 'scope'.
[lib/symboldatabase.h:1090] -> [lib/symboldatabase.cpp:3648]: (style, inconclusive) Function 'findVariableType' argument 2 names different: declaration 'type' definition 'typeTok'.
[lib/symboldatabase.h:1101] -> [lib/symboldatabase.cpp:4308]: (style, inconclusive) Function 'findType' argument 1 names different: declaration 'tok' definition 'startTok'.
[lib/symboldatabase.h:1176] -> [lib/symboldatabase.cpp:4349]: (style, inconclusive) Function 'findTypeInNested' argument 1 names different: declaration 'tok' definition 'startTok'.
[lib/symboldatabase.h:1193] -> [lib/symboldatabase.cpp:4501]: (style, inconclusive) Function 'setValueType' argument 2 names different: declaration 'enumerators' definition 'enumerator'.
[lib/path.h:159] -> [lib/path.cpp:247]: (style, inconclusive) Function 'isCPP' argument 1 names different: declaration 'extensionInLowerCase' definition 'path'.
[lib/path.h:145] -> [lib/path.cpp:266]: (style, inconclusive) Function 'acceptFile' argument 1 names different: declaration 'filename' definition 'path'.
2017-04-03 00:06:46 +02:00
ErrorLogger : : ErrorMessage : : ErrorMessage ( const std : : list < FileLocation > & callStack , const std : : string & file1 , Severity : : SeverityType severity , const std : : string & msg , const std : : string & id , const CWE & cwe , bool inconclusive ) :
Mapped toomanyconfigs ,AssignmentAddressToInteger
,AssignmentIntegerToAddress ,CastIntegerToAddressAtReturn
,CastAddressToIntegerAtReturn ,assertWithSideEffect ,assignmentInAssert
,uselessAssignmentArg ,uselessAssignmentPtrArg
,comparisonOfFuncReturningBoolError
,comparisonOfTwoFuncsReturningBoolError ,comparisonOfBoolWithBoolError
,incrementboolean ,comparisonOfBoolWithInt ,compareBoolExpressionWithInt
,negativeIndex ,pointerOutOfBounds ,arrayIndexThenCheck
,possibleBufferAccessOutOfBounds ,argumentSize
,arrayIndexOutOfBoundsCond ,noConstructor ,copyCtorPointerCopying
,noCopyConstructor ,uninitMemberVar ,operatorEqVarError
,unusedPrivateFunction ,memsetClassFloat ,mallocOnClassWarning
,operatorEq ,thisSubtraction ,operatorEqRetRefThis ,operatorEqToSelf
,useInitializationList ,duplInheritedMember ,assignIfError
,comparisonError ,multiCondition ,mismatchingBitAnd
,oppositeInnerCondition ,incorrectLogicOperator ,redundantCondition
,moduloAlwaysTrueFalse to their CWEs ids.
2016-02-20 23:56:36 +01:00
_callStack ( callStack ) , // locations for this error message
_id ( id ) , // set the message id
lib: fix a bunch of warnings about differing function arguments in definition and declaration.
[lib/token.h:72] -> [lib/token.cpp:36]: (style, inconclusive) Function 'Token' argument 1 names different: declaration 'tokensBack' definition 't'.
[lib/token.h:445] -> [lib/token.cpp:497]: (style, inconclusive) Function 'multiCompare' argument 1 names different: declaration 'needle' definition 'tok'.
[lib/checkio.h:73] -> [lib/checkio.cpp:1385]: (style, inconclusive) Function 'ArgumentInfo' argument 3 names different: declaration 'isCPP' definition '_isCPP'.
[lib/checkother.h:216] -> [lib/checkother.cpp:2136]: (style, inconclusive) Function 'checkComparisonFunctionIsAlwaysTrueOrFalseError' argument 2 names different: declaration 'strFunctionName' definition 'functionName'.
[lib/errorlogger.h:214] -> [lib/errorlogger.cpp:51]: (style, inconclusive) Function 'ErrorMessage' argument 2 names different: declaration 'file0' definition 'file0_'.
[lib/errorlogger.h:215] -> [lib/errorlogger.cpp:65]: (style, inconclusive) Function 'ErrorMessage' argument 2 names different: declaration 'file0' definition 'file0_'.
[lib/library.h:327] -> [lib/library.cpp:1043]: (style, inconclusive) Function 'ignorefunction' argument 1 names different: declaration 'function' definition 'functionName'.
[lib/mathlib.h:112] -> [lib/mathlib.cpp:1275]: (style, inconclusive) Function 'isNullValue' argument 1 names different: declaration 'tok' definition 'str'.
[lib/preprocessor.h:91] -> [lib/preprocessor.cpp:122]: (style, inconclusive) Function 'setDirectives' argument 1 names different: declaration 'tokens' definition 'tokens1'.
[lib/symboldatabase.h:860] -> [lib/symboldatabase.cpp:1801]: (style, inconclusive) Function 'argsMatch' argument 1 names different: declaration 'info' definition 'scope'.
[lib/symboldatabase.h:1171] -> [lib/symboldatabase.cpp:2048]: (style, inconclusive) Function 'addClassFunction' argument 1 names different: declaration 'info' definition 'scope'.
[lib/symboldatabase.h:1174] -> [lib/symboldatabase.cpp:2208]: (style, inconclusive) Function 'addNewFunction' argument 1 names different: declaration 'info' definition 'scope'.
[lib/symboldatabase.h:1090] -> [lib/symboldatabase.cpp:3648]: (style, inconclusive) Function 'findVariableType' argument 2 names different: declaration 'type' definition 'typeTok'.
[lib/symboldatabase.h:1101] -> [lib/symboldatabase.cpp:4308]: (style, inconclusive) Function 'findType' argument 1 names different: declaration 'tok' definition 'startTok'.
[lib/symboldatabase.h:1176] -> [lib/symboldatabase.cpp:4349]: (style, inconclusive) Function 'findTypeInNested' argument 1 names different: declaration 'tok' definition 'startTok'.
[lib/symboldatabase.h:1193] -> [lib/symboldatabase.cpp:4501]: (style, inconclusive) Function 'setValueType' argument 2 names different: declaration 'enumerators' definition 'enumerator'.
[lib/path.h:159] -> [lib/path.cpp:247]: (style, inconclusive) Function 'isCPP' argument 1 names different: declaration 'extensionInLowerCase' definition 'path'.
[lib/path.h:145] -> [lib/path.cpp:266]: (style, inconclusive) Function 'acceptFile' argument 1 names different: declaration 'filename' definition 'path'.
2017-04-03 00:06:46 +02:00
file0 ( file1 ) ,
Mapped toomanyconfigs ,AssignmentAddressToInteger
,AssignmentIntegerToAddress ,CastIntegerToAddressAtReturn
,CastAddressToIntegerAtReturn ,assertWithSideEffect ,assignmentInAssert
,uselessAssignmentArg ,uselessAssignmentPtrArg
,comparisonOfFuncReturningBoolError
,comparisonOfTwoFuncsReturningBoolError ,comparisonOfBoolWithBoolError
,incrementboolean ,comparisonOfBoolWithInt ,compareBoolExpressionWithInt
,negativeIndex ,pointerOutOfBounds ,arrayIndexThenCheck
,possibleBufferAccessOutOfBounds ,argumentSize
,arrayIndexOutOfBoundsCond ,noConstructor ,copyCtorPointerCopying
,noCopyConstructor ,uninitMemberVar ,operatorEqVarError
,unusedPrivateFunction ,memsetClassFloat ,mallocOnClassWarning
,operatorEq ,thisSubtraction ,operatorEqRetRefThis ,operatorEqToSelf
,useInitializationList ,duplInheritedMember ,assignIfError
,comparisonError ,multiCondition ,mismatchingBitAnd
,oppositeInnerCondition ,incorrectLogicOperator ,redundantCondition
,moduloAlwaysTrueFalse to their CWEs ids.
2016-02-20 23:56:36 +01:00
_severity ( severity ) , // severity for this error message
_cwe ( cwe . id ) ,
_inconclusive ( inconclusive )
{
// set the summary and verbose messages
setmsg ( msg ) ;
}
2012-05-06 10:17:15 +02:00
ErrorLogger : : ErrorMessage : : ErrorMessage ( const std : : list < const Token * > & callstack , const TokenList * list , Severity : : SeverityType severity , const std : : string & id , const std : : string & msg , bool inconclusive )
2015-04-25 17:48:11 +02:00
: _id ( id ) , _severity ( severity ) , _cwe ( 0U ) , _inconclusive ( inconclusive )
2012-05-06 10:17:15 +02:00
{
// Format callstack
for ( std : : list < const Token * > : : const_iterator it = callstack . begin ( ) ; it ! = callstack . end ( ) ; + + it ) {
// --errorlist can provide null values here
if ( ! ( * it ) )
continue ;
2018-04-11 09:44:35 +02:00
_callStack . emplace_back ( * it , list ) ;
Mapped toomanyconfigs ,AssignmentAddressToInteger
,AssignmentIntegerToAddress ,CastIntegerToAddressAtReturn
,CastAddressToIntegerAtReturn ,assertWithSideEffect ,assignmentInAssert
,uselessAssignmentArg ,uselessAssignmentPtrArg
,comparisonOfFuncReturningBoolError
,comparisonOfTwoFuncsReturningBoolError ,comparisonOfBoolWithBoolError
,incrementboolean ,comparisonOfBoolWithInt ,compareBoolExpressionWithInt
,negativeIndex ,pointerOutOfBounds ,arrayIndexThenCheck
,possibleBufferAccessOutOfBounds ,argumentSize
,arrayIndexOutOfBoundsCond ,noConstructor ,copyCtorPointerCopying
,noCopyConstructor ,uninitMemberVar ,operatorEqVarError
,unusedPrivateFunction ,memsetClassFloat ,mallocOnClassWarning
,operatorEq ,thisSubtraction ,operatorEqRetRefThis ,operatorEqToSelf
,useInitializationList ,duplInheritedMember ,assignIfError
,comparisonError ,multiCondition ,mismatchingBitAnd
,oppositeInnerCondition ,incorrectLogicOperator ,redundantCondition
,moduloAlwaysTrueFalse to their CWEs ids.
2016-02-20 23:56:36 +01:00
}
if ( list & & ! list - > getFiles ( ) . empty ( ) )
file0 = list - > getFiles ( ) [ 0 ] ;
setmsg ( msg ) ;
}
ErrorLogger : : ErrorMessage : : ErrorMessage ( const std : : list < const Token * > & callstack , const TokenList * list , Severity : : SeverityType severity , const std : : string & id , const std : : string & msg , const CWE & cwe , bool inconclusive )
: _id ( id ) , _severity ( severity ) , _cwe ( cwe . id ) , _inconclusive ( inconclusive )
{
// Format callstack
for ( std : : list < const Token * > : : const_iterator it = callstack . begin ( ) ; it ! = callstack . end ( ) ; + + it ) {
// --errorlist can provide null values here
if ( ! ( * it ) )
continue ;
2018-04-11 09:44:35 +02:00
_callStack . emplace_back ( * it , list ) ;
2012-05-06 10:17:15 +02:00
}
if ( list & & ! list - > getFiles ( ) . empty ( ) )
file0 = list - > getFiles ( ) [ 0 ] ;
setmsg ( msg ) ;
}
2017-05-16 22:38:13 +02:00
ErrorLogger : : ErrorMessage : : ErrorMessage ( const ErrorPath & errorPath , const TokenList * tokenList , Severity : : SeverityType severity , const char id [ ] , const std : : string & msg , const CWE & cwe , bool inconclusive )
: _id ( id ) , _severity ( severity ) , _cwe ( cwe . id ) , _inconclusive ( inconclusive )
{
// Format callstack
for ( ErrorPath : : const_iterator it = errorPath . begin ( ) ; it ! = errorPath . end ( ) ; + + it ) {
const Token * tok = it - > first ;
const std : : string & info = it - > second ;
// --errorlist can provide null values here
if ( tok )
2018-04-11 09:44:35 +02:00
_callStack . emplace_back ( tok , info , tokenList ) ;
2017-05-16 22:38:13 +02:00
}
if ( tokenList & & ! tokenList - > getFiles ( ) . empty ( ) )
file0 = tokenList - > getFiles ( ) [ 0 ] ;
setmsg ( msg ) ;
}
2016-10-29 15:50:08 +02:00
ErrorLogger : : ErrorMessage : : ErrorMessage ( const tinyxml2 : : XMLElement * const errmsg )
2017-08-16 16:53:04 +02:00
: _severity ( Severity : : none ) ,
2016-10-29 15:50:08 +02:00
_cwe ( 0U ) ,
2017-08-16 16:53:04 +02:00
_inconclusive ( false )
2016-10-29 12:18:11 +02:00
{
2017-08-16 16:53:04 +02:00
const char * const unknown = " <UNKNOWN> " ;
const char * attr = errmsg - > Attribute ( " id " ) ;
_id = attr ? attr : unknown ;
attr = errmsg - > Attribute ( " severity " ) ;
_severity = attr ? Severity : : fromString ( attr ) : Severity : : none ;
attr = errmsg - > Attribute ( " cwe " ) ;
2016-10-29 12:18:11 +02:00
std : : istringstream ( attr ? attr : " 0 " ) > > _cwe . id ;
2017-08-16 16:53:04 +02:00
2016-10-29 12:18:11 +02:00
attr = errmsg - > Attribute ( " inconclusive " ) ;
_inconclusive = attr & & ( std : : strcmp ( attr , " true " ) = = 0 ) ;
2017-08-16 16:53:04 +02:00
attr = errmsg - > Attribute ( " msg " ) ;
2018-06-17 07:54:50 +02:00
mShortMessage = attr ? attr : " " ;
2017-08-16 16:53:04 +02:00
attr = errmsg - > Attribute ( " verbose " ) ;
2018-06-17 07:55:47 +02:00
mVerboseMessage = attr ? attr : " " ;
2017-08-16 16:53:04 +02:00
2016-10-29 12:18:11 +02:00
for ( const tinyxml2 : : XMLElement * e = errmsg - > FirstChildElement ( ) ; e ; e = e - > NextSiblingElement ( ) ) {
if ( std : : strcmp ( e - > Name ( ) , " location " ) = = 0 ) {
2017-05-16 22:38:13 +02:00
const char * strfile = e - > Attribute ( " file " ) ;
const char * strinfo = e - > Attribute ( " info " ) ;
const char * strline = e - > Attribute ( " line " ) ;
2017-08-16 16:53:04 +02:00
const char * file = strfile ? strfile : unknown ;
const char * info = strinfo ? strinfo : " " ;
const int line = strline ? std : : atoi ( strline ) : 0 ;
2018-04-11 09:44:35 +02:00
_callStack . emplace_back ( file , info , line ) ;
2016-10-29 12:18:11 +02:00
}
}
}
2018-04-09 06:43:48 +02:00
static std : : string replaceStr ( std : : string s , const std : : string & from , const std : : string & to )
{
std : : string : : size_type pos = 0 ;
while ( std : : string : : npos ! = ( pos = s . find ( from , pos ) ) ) {
s = s . substr ( 0 , pos ) + to + s . substr ( pos + from . size ( ) ) ;
pos + = to . size ( ) ;
}
return s ;
}
2010-11-11 19:54:43 +01:00
void ErrorLogger : : ErrorMessage : : setmsg ( const std : : string & msg )
{
2011-12-30 00:22:16 +01:00
// If a message ends to a '\n' and contains only a one '\n'
2018-06-17 07:55:47 +02:00
// it will cause the mVerboseMessage to be empty which will show
2011-12-30 00:22:16 +01:00
// as an empty message to the user if --verbose is used.
// Even this doesn't cause problems with messages that have multiple
2018-10-08 13:58:21 +02:00
// lines, none of the error messages should end into it.
2017-04-01 18:14:18 +02:00
assert ( ! endsWith ( msg , ' \n ' ) ) ;
2011-12-30 00:22:16 +01:00
2010-12-30 22:07:27 +01:00
// The summary and verbose message are separated by a newline
// If there is no newline then both the summary and verbose messages
// are the given message
2015-08-15 20:24:26 +02:00
const std : : string : : size_type pos = msg . find ( ' \n ' ) ;
2018-06-17 07:59:48 +02:00
const std : : string symbolName = mSymbolNames . empty ( ) ? std : : string ( ) : mSymbolNames . substr ( 0 , mSymbolNames . find ( ' \n ' ) ) ;
2011-10-13 20:53:06 +02:00
if ( pos = = std : : string : : npos ) {
2018-06-17 07:54:50 +02:00
mShortMessage = replaceStr ( msg , " $symbol " , symbolName ) ;
2018-06-17 07:55:47 +02:00
mVerboseMessage = replaceStr ( msg , " $symbol " , symbolName ) ;
2018-04-09 06:43:48 +02:00
} else if ( msg . compare ( 0 , 8 , " $symbol: " ) = = 0 ) {
2018-06-17 07:59:48 +02:00
mSymbolNames + = msg . substr ( 8 , pos - 7 ) ;
2018-04-09 06:43:48 +02:00
setmsg ( msg . substr ( pos + 1 ) ) ;
2011-10-13 20:53:06 +02:00
} else {
2018-06-17 07:54:50 +02:00
mShortMessage = replaceStr ( msg . substr ( 0 , pos ) , " $symbol " , symbolName ) ;
2018-06-17 07:55:47 +02:00
mVerboseMessage = replaceStr ( msg . substr ( pos + 1 ) , " $symbol " , symbolName ) ;
2010-11-11 19:54:43 +01:00
}
}
2018-04-09 06:43:48 +02:00
Suppressions : : ErrorMessage ErrorLogger : : ErrorMessage : : toSuppressionsErrorMessage ( ) const
{
Suppressions : : ErrorMessage ret ;
ret . errorId = _id ;
if ( ! _callStack . empty ( ) ) {
ret . setFileName ( _callStack . back ( ) . getfile ( false ) ) ;
ret . lineNumber = _callStack . back ( ) . line ;
}
ret . inconclusive = _inconclusive ;
2018-06-17 07:59:48 +02:00
ret . symbolNames = mSymbolNames ;
2018-04-09 06:43:48 +02:00
return ret ;
}
2009-02-19 23:21:18 +01:00
std : : string ErrorLogger : : ErrorMessage : : serialize ( ) const
{
2010-12-30 22:07:27 +01:00
// Serialize this message into a simple string
2009-02-19 23:21:18 +01:00
std : : ostringstream oss ;
oss < < _id . length ( ) < < " " < < _id ;
2010-07-14 18:36:34 +02:00
oss < < Severity : : toString ( _severity ) . length ( ) < < " " < < Severity : : toString ( _severity ) ;
2016-02-27 16:03:50 +01:00
oss < < MathLib : : toString ( _cwe . id ) . length ( ) < < " " < < MathLib : : toString ( _cwe . id ) ;
2011-10-13 20:53:06 +02:00
if ( _inconclusive ) {
2011-04-16 13:42:48 +02:00
const std : : string inconclusive ( " inconclusive " ) ;
oss < < inconclusive . length ( ) < < " " < < inconclusive ;
}
2015-01-17 15:58:36 +01:00
2018-06-17 07:54:50 +02:00
const std : : string saneShortMessage = fixInvalidChars ( mShortMessage ) ;
2018-06-17 07:55:47 +02:00
const std : : string saneVerboseMessage = fixInvalidChars ( mVerboseMessage ) ;
2015-01-17 15:58:36 +01:00
oss < < saneShortMessage . length ( ) < < " " < < saneShortMessage ;
oss < < saneVerboseMessage . length ( ) < < " " < < saneVerboseMessage ;
2009-02-19 23:21:18 +01:00
oss < < _callStack . size ( ) < < " " ;
2017-05-16 22:58:02 +02:00
for ( std : : list < ErrorLogger : : ErrorMessage : : FileLocation > : : const_iterator loc = _callStack . begin ( ) ; loc ! = _callStack . end ( ) ; + + loc ) {
2009-02-19 23:21:18 +01:00
std : : ostringstream smallStream ;
2017-05-16 22:58:02 +02:00
smallStream < < ( * loc ) . line < < ' : ' < < ( * loc ) . getfile ( ) < < ' \t ' < < loc - > getinfo ( ) ;
2009-02-19 23:21:18 +01:00
oss < < smallStream . str ( ) . length ( ) < < " " < < smallStream . str ( ) ;
}
2010-12-24 11:13:57 +01:00
2009-02-19 23:21:18 +01:00
return oss . str ( ) ;
}
bool ErrorLogger : : ErrorMessage : : deserialize ( const std : : string & data )
{
2011-04-14 18:02:01 +02:00
_inconclusive = false ;
2009-02-19 23:21:18 +01:00
_callStack . clear ( ) ;
std : : istringstream iss ( data ) ;
2015-11-29 10:49:10 +01:00
std : : array < std : : string , 5 > results ;
std : : size_t elem = 0 ;
2011-10-13 20:53:06 +02:00
while ( iss . good ( ) ) {
2009-02-19 23:21:18 +01:00
unsigned int len = 0 ;
2010-04-02 07:30:58 +02:00
if ( ! ( iss > > len ) )
2009-02-19 23:21:18 +01:00
return false ;
iss . get ( ) ;
std : : string temp ;
2011-10-13 20:53:06 +02:00
for ( unsigned int i = 0 ; i < len & & iss . good ( ) ; + + i ) {
2018-05-29 13:24:48 +02:00
const char c = static_cast < char > ( iss . get ( ) ) ;
2009-03-08 19:50:19 +01:00
temp . append ( 1 , c ) ;
}
2009-02-19 23:21:18 +01:00
2011-10-13 20:53:06 +02:00
if ( temp = = " inconclusive " ) {
2011-04-14 18:02:01 +02:00
_inconclusive = true ;
2011-04-16 13:42:48 +02:00
continue ;
2011-04-14 18:02:01 +02:00
}
2015-11-29 10:49:10 +01:00
results [ elem + + ] = temp ;
if ( elem = = 5 )
2009-02-19 23:21:18 +01:00
break ;
}
2015-11-29 10:49:10 +01:00
if ( elem ! = 5 )
2017-08-09 20:00:26 +02:00
throw InternalError ( nullptr , " Internal Error: Deserialization of error message failed " ) ;
2015-01-17 15:56:09 +01:00
2009-02-19 23:21:18 +01:00
_id = results [ 0 ] ;
2010-07-14 18:36:34 +02:00
_severity = Severity : : fromString ( results [ 1 ] ) ;
2015-07-25 13:23:48 +02:00
std : : istringstream scwe ( results [ 2 ] ) ;
2016-02-27 16:03:50 +01:00
scwe > > _cwe . id ;
2018-06-17 07:54:50 +02:00
mShortMessage = results [ 3 ] ;
2018-06-17 07:55:47 +02:00
mVerboseMessage = results [ 4 ] ;
2009-02-19 23:21:18 +01:00
unsigned int stackSize = 0 ;
2010-04-02 07:30:58 +02:00
if ( ! ( iss > > stackSize ) )
2009-02-19 23:21:18 +01:00
return false ;
2011-10-13 20:53:06 +02:00
while ( iss . good ( ) ) {
2009-02-19 23:21:18 +01:00
unsigned int len = 0 ;
2010-04-02 07:30:58 +02:00
if ( ! ( iss > > len ) )
2009-02-19 23:21:18 +01:00
return false ;
iss . get ( ) ;
std : : string temp ;
2011-10-13 20:53:06 +02:00
for ( unsigned int i = 0 ; i < len & & iss . good ( ) ; + + i ) {
2016-02-27 16:03:50 +01:00
const char c = static_cast < char > ( iss . get ( ) ) ;
2009-03-08 19:50:19 +01:00
temp . append ( 1 , c ) ;
}
2009-02-19 23:21:18 +01:00
2016-01-20 14:46:15 +01:00
const std : : string : : size_type colonPos = temp . find ( ' : ' ) ;
if ( colonPos = = std : : string : : npos )
2017-08-09 20:00:26 +02:00
throw InternalError ( nullptr , " Internal Error: No colon found in <filename:line> pattern " ) ;
2017-05-16 22:58:02 +02:00
const std : : string : : size_type tabPos = temp . find ( ' \t ' ) ;
if ( tabPos = = std : : string : : npos )
2017-08-09 20:00:26 +02:00
throw InternalError ( nullptr , " Internal Error: No tab found in <filename:line> pattern " ) ;
2017-05-16 22:58:02 +02:00
const std : : string tempinfo = temp . substr ( tabPos + 1 ) ;
temp . erase ( tabPos ) ;
const std : : string tempfile = temp . substr ( colonPos + 1 ) ;
temp . erase ( colonPos ) ;
const std : : string templine = temp ;
2009-02-19 23:21:18 +01:00
ErrorLogger : : ErrorMessage : : FileLocation loc ;
2017-05-16 22:58:02 +02:00
loc . setfile ( tempfile ) ;
loc . setinfo ( tempinfo ) ;
std : : istringstream fiss ( templine ) ;
2009-02-19 23:21:18 +01:00
fiss > > loc . line ;
_callStack . push_back ( loc ) ;
2010-04-02 07:30:58 +02:00
if ( _callStack . size ( ) > = stackSize )
2009-02-19 23:21:18 +01:00
break ;
}
return true ;
}
2017-07-29 18:56:22 +02:00
std : : string ErrorLogger : : ErrorMessage : : getXMLHeader ( )
2009-06-15 20:36:39 +02:00
{
2010-12-30 22:07:27 +01:00
// xml_version 1 is the default xml format
2013-08-07 16:30:55 +02:00
tinyxml2 : : XMLPrinter printer ;
2010-12-02 17:32:51 +01:00
2013-08-07 16:30:55 +02:00
// standard xml header
printer . PushDeclaration ( " xml version= \" 1.0 \" encoding= \" UTF-8 \" " ) ;
2010-12-30 22:07:27 +01:00
2013-08-07 16:30:55 +02:00
// header
2014-03-01 11:15:08 +01:00
printer . OpenElement ( " results " , false ) ;
2017-07-29 18:56:22 +02:00
printer . PushAttribute ( " version " , 2 ) ;
printer . OpenElement ( " cppcheck " , false ) ;
printer . PushAttribute ( " version " , CppCheck : : version ( ) ) ;
printer . CloseElement ( false ) ;
printer . OpenElement ( " errors " , false ) ;
2010-12-22 10:29:23 +01:00
2013-08-07 16:30:55 +02:00
return std : : string ( printer . CStr ( ) ) + ' > ' ;
2009-06-15 20:36:39 +02:00
}
2017-07-29 18:56:22 +02:00
std : : string ErrorLogger : : ErrorMessage : : getXMLFooter ( )
2009-06-15 20:36:39 +02:00
{
2017-07-29 18:56:22 +02:00
return " </errors> \n </results> " ;
2009-10-27 22:10:14 +01:00
}
2014-04-13 09:50:57 +02:00
// There is no utf-8 support around but the strings should at least be safe for to tinyxml2.
2015-06-18 19:07:51 +02:00
// See #5300 "Invalid encoding in XML output" and #6431 "Invalid XML created - Invalid encoding of string literal "
std : : string ErrorLogger : : ErrorMessage : : fixInvalidChars ( const std : : string & raw )
2014-04-13 09:50:57 +02:00
{
std : : string result ;
result . reserve ( raw . length ( ) ) ;
std : : string : : const_iterator from = raw . begin ( ) ;
while ( from ! = raw . end ( ) ) {
2014-04-27 13:27:39 +02:00
if ( std : : isprint ( static_cast < unsigned char > ( * from ) ) ) {
2014-04-13 09:50:57 +02:00
result . push_back ( * from ) ;
} else {
std : : ostringstream es ;
// straight cast to (unsigned) doesn't work out.
2015-07-04 13:19:21 +02:00
const unsigned uFrom = ( unsigned char ) * from ;
2016-02-01 18:53:46 +01:00
es < < ' \\ ' < < std : : setbase ( 8 ) < < std : : setw ( 3 ) < < std : : setfill ( ' 0 ' ) < < uFrom ;
2014-04-13 09:50:57 +02:00
result + = es . str ( ) ;
}
+ + from ;
}
return result ;
}
2017-07-29 18:56:22 +02:00
std : : string ErrorLogger : : ErrorMessage : : toXML ( ) const
2009-02-10 22:51:52 +01:00
{
2017-08-09 20:00:26 +02:00
tinyxml2 : : XMLPrinter printer ( nullptr , false , 2 ) ;
2017-07-29 18:56:22 +02:00
printer . OpenElement ( " error " , false ) ;
printer . PushAttribute ( " id " , _id . c_str ( ) ) ;
printer . PushAttribute ( " severity " , Severity : : toString ( _severity ) . c_str ( ) ) ;
2018-06-17 07:54:50 +02:00
printer . PushAttribute ( " msg " , fixInvalidChars ( mShortMessage ) . c_str ( ) ) ;
2018-06-17 07:55:47 +02:00
printer . PushAttribute ( " verbose " , fixInvalidChars ( mVerboseMessage ) . c_str ( ) ) ;
2017-07-29 18:56:22 +02:00
if ( _cwe . id )
printer . PushAttribute ( " cwe " , _cwe . id ) ;
if ( _inconclusive )
printer . PushAttribute ( " inconclusive " , " true " ) ;
for ( std : : list < FileLocation > : : const_reverse_iterator it = _callStack . rbegin ( ) ; it ! = _callStack . rend ( ) ; + + it ) {
printer . OpenElement ( " location " , false ) ;
if ( ! file0 . empty ( ) & & ( * it ) . getfile ( ) ! = file0 )
printer . PushAttribute ( " file0 " , Path : : toNativeSeparators ( file0 ) . c_str ( ) ) ;
printer . PushAttribute ( " file " , ( * it ) . getfile ( ) . c_str ( ) ) ;
2018-09-25 06:14:26 +02:00
printer . PushAttribute ( " line " , std : : max ( ( * it ) . line , 0 ) ) ;
2017-07-29 18:56:22 +02:00
if ( ! it - > getinfo ( ) . empty ( ) )
printer . PushAttribute ( " info " , it - > getinfo ( ) . c_str ( ) ) ;
2014-03-01 11:15:08 +01:00
printer . CloseElement ( false ) ;
2010-12-01 21:24:17 +01:00
}
2018-06-17 07:59:48 +02:00
for ( std : : string : : size_type pos = 0 ; pos < mSymbolNames . size ( ) ; ) {
const std : : string : : size_type pos2 = mSymbolNames . find ( ' \n ' , pos ) ;
2018-04-09 06:43:48 +02:00
std : : string symbolName ;
if ( pos2 = = std : : string : : npos ) {
2018-06-17 07:59:48 +02:00
symbolName = mSymbolNames . substr ( pos ) ;
2018-04-09 06:43:48 +02:00
pos = pos2 ;
} else {
2018-06-17 07:59:48 +02:00
symbolName = mSymbolNames . substr ( pos , pos2 - pos ) ;
2018-04-09 06:43:48 +02:00
pos = pos2 + 1 ;
}
printer . OpenElement ( " symbol " , false ) ;
printer . PushText ( symbolName . c_str ( ) ) ;
printer . CloseElement ( false ) ;
}
2017-07-29 18:56:22 +02:00
printer . CloseElement ( false ) ;
return printer . CStr ( ) ;
2009-02-10 22:51:52 +01:00
}
2009-09-05 21:01:49 +02:00
void ErrorLogger : : ErrorMessage : : findAndReplace ( std : : string & source , const std : : string & searchFor , const std : : string & replaceWith )
2009-02-10 22:51:52 +01:00
{
2009-09-05 21:01:49 +02:00
std : : string : : size_type index = 0 ;
2011-10-13 20:53:06 +02:00
while ( ( index = source . find ( searchFor , index ) ) ! = std : : string : : npos ) {
2009-09-05 21:01:49 +02:00
source . replace ( index , searchFor . length ( ) , replaceWith ) ;
2015-09-02 16:06:19 +02:00
index + = replaceWith . length ( ) ;
2009-09-05 21:01:49 +02:00
}
}
2018-04-23 09:18:32 +02:00
// TODO: read info from some shared resource instead?
static std : : string readCode ( const std : : string & file , unsigned int linenr , unsigned int column , const char endl [ ] )
{
std : : ifstream fin ( file ) ;
std : : string line ;
while ( linenr > 0 & & std : : getline ( fin , line ) ) {
linenr - - ;
}
const std : : string : : size_type endPos = line . find_last_not_of ( " \r \n \t " ) ;
if ( endPos + 1 < line . size ( ) )
line . erase ( endPos + 1 ) ;
2018-04-23 14:11:33 +02:00
std : : string : : size_type pos = 0 ;
2018-06-17 16:39:28 +02:00
while ( ( pos = line . find ( ' \t ' , pos ) ) ! = std : : string : : npos )
2018-04-23 14:11:33 +02:00
line [ pos ] = ' ' ;
2018-04-23 12:21:18 +02:00
return line + endl + std : : string ( ( column > 0 ? column - 1 : column ) , ' ' ) + ' ^ ' ;
2018-04-23 09:18:32 +02:00
}
2018-04-23 12:21:18 +02:00
std : : string ErrorLogger : : ErrorMessage : : toString ( bool verbose , const std : : string & templateFormat , const std : : string & templateLocation ) const
2009-09-05 21:01:49 +02:00
{
2010-12-30 22:07:27 +01:00
// Save this ErrorMessage in plain text.
// No template is given
2018-04-23 12:21:18 +02:00
if ( templateFormat . empty ( ) ) {
2009-09-05 21:01:49 +02:00
std : : ostringstream text ;
2010-04-02 07:30:58 +02:00
if ( ! _callStack . empty ( ) )
2009-09-05 21:01:49 +02:00
text < < callStackToString ( _callStack ) < < " : " ;
2012-05-06 19:37:41 +02:00
if ( _severity ! = Severity : : none ) {
text < < ' ( ' < < Severity : : toString ( _severity ) ;
if ( _inconclusive )
text < < " , inconclusive " ;
text < < " ) " ;
}
2018-06-17 07:55:47 +02:00
text < < ( verbose ? mVerboseMessage : mShortMessage ) ;
2009-09-05 21:01:49 +02:00
return text . str ( ) ;
}
2010-12-30 22:07:27 +01:00
2018-04-23 12:21:18 +02:00
// template is given. Reformat the output according to it
std : : string result = templateFormat ;
// Support a few special characters to allow to specific formatting, see http://sourceforge.net/apps/phpbb/cppcheck/viewtopic.php?f=4&t=494&sid=21715d362c0dbafd3791da4d9522f814
// Substitution should be done first so messages from cppcheck never get translated.
findAndReplace ( result , " \\ b " , " \b " ) ;
findAndReplace ( result , " \\ n " , " \n " ) ;
findAndReplace ( result , " \\ r " , " \r " ) ;
findAndReplace ( result , " \\ t " , " \t " ) ;
findAndReplace ( result , " {id} " , _id ) ;
if ( result . find ( " {inconclusive: " ) ! = std : : string : : npos ) {
const std : : string : : size_type pos1 = result . find ( " {inconclusive: " ) ;
2018-06-17 16:39:28 +02:00
const std : : string : : size_type pos2 = result . find ( ' } ' , pos1 + 1 ) ;
2018-04-23 12:21:18 +02:00
const std : : string replaceFrom = result . substr ( pos1 , pos2 - pos1 + 1 ) ;
2018-04-24 11:10:41 +02:00
const std : : string replaceWith = _inconclusive ? result . substr ( pos1 + 14 , pos2 - pos1 - 14 ) : std : : string ( ) ;
2018-04-23 12:21:18 +02:00
findAndReplace ( result , replaceFrom , replaceWith ) ;
}
findAndReplace ( result , " {severity} " , Severity : : toString ( _severity ) ) ;
2018-08-21 13:58:19 +02:00
findAndReplace ( result , " {cwe} " , MathLib : : toString ( _cwe . id ) ) ;
2018-06-17 07:55:47 +02:00
findAndReplace ( result , " {message} " , verbose ? mVerboseMessage : mShortMessage ) ;
2018-04-23 12:21:18 +02:00
findAndReplace ( result , " {callstack} " , _callStack . empty ( ) ? emptyString : callStackToString ( _callStack ) ) ;
if ( ! _callStack . empty ( ) ) {
findAndReplace ( result , " {file} " , _callStack . back ( ) . getfile ( ) ) ;
findAndReplace ( result , " {line} " , MathLib : : toString ( _callStack . back ( ) . line ) ) ;
findAndReplace ( result , " {column} " , MathLib : : toString ( _callStack . back ( ) . col ) ) ;
if ( result . find ( " {code} " ) ! = std : : string : : npos ) {
2018-06-17 16:39:28 +02:00
const std : : string : : size_type pos = result . find ( ' \r ' ) ;
2018-04-23 12:21:18 +02:00
const char * endl ;
if ( pos = = std : : string : : npos )
endl = " \n " ;
else if ( pos + 1 < result . size ( ) & & result [ pos + 1 ] = = ' \n ' )
endl = " \r \n " ;
else
endl = " \r " ;
findAndReplace ( result , " {code} " , readCode ( _callStack . back ( ) . getfile ( ) , _callStack . back ( ) . line , _callStack . back ( ) . col , endl ) ) ;
2017-05-22 11:25:58 +02:00
}
2018-04-23 12:21:18 +02:00
} else {
findAndReplace ( result , " {file} " , " nofile " ) ;
findAndReplace ( result , " {line} " , " 0 " ) ;
findAndReplace ( result , " {column} " , " 0 " ) ;
findAndReplace ( result , " {code} " , emptyString ) ;
2017-05-19 17:09:49 +02:00
}
2018-04-23 12:21:18 +02:00
if ( ! templateLocation . empty ( ) & & _callStack . size ( ) > = 2U ) {
for ( const FileLocation & fileLocation : _callStack ) {
std : : string text = templateLocation ;
findAndReplace ( text , " \\ b " , " \b " ) ;
findAndReplace ( text , " \\ n " , " \n " ) ;
findAndReplace ( text , " \\ r " , " \r " ) ;
findAndReplace ( text , " \\ t " , " \t " ) ;
findAndReplace ( text , " {file} " , fileLocation . getfile ( ) ) ;
findAndReplace ( text , " {line} " , MathLib : : toString ( fileLocation . line ) ) ;
findAndReplace ( text , " {column} " , MathLib : : toString ( fileLocation . col ) ) ;
2018-06-17 07:54:50 +02:00
findAndReplace ( text , " {info} " , fileLocation . getinfo ( ) . empty ( ) ? mShortMessage : fileLocation . getinfo ( ) ) ;
2018-04-23 12:21:18 +02:00
if ( text . find ( " {code} " ) ! = std : : string : : npos ) {
2018-06-17 16:39:28 +02:00
const std : : string : : size_type pos = text . find ( ' \r ' ) ;
2018-04-23 09:18:32 +02:00
const char * endl ;
if ( pos = = std : : string : : npos )
endl = " \n " ;
2018-04-23 12:21:18 +02:00
else if ( pos + 1 < text . size ( ) & & text [ pos + 1 ] = = ' \n ' )
2018-04-23 09:18:32 +02:00
endl = " \r \n " ;
else
endl = " \r " ;
2018-04-23 12:21:18 +02:00
findAndReplace ( text , " {code} " , readCode ( fileLocation . getfile ( ) , fileLocation . line , fileLocation . col , endl ) ) ;
2018-04-23 09:18:32 +02:00
}
2018-04-23 12:21:18 +02:00
result + = ' \n ' + text ;
2009-09-05 21:01:49 +02:00
}
}
2018-04-23 12:21:18 +02:00
return result ;
2009-02-10 22:51:52 +01:00
}
2018-04-09 06:43:48 +02:00
void ErrorLogger : : reportUnmatchedSuppressions ( const std : : list < Suppressions : : Suppression > & unmatched )
2011-02-16 02:12:15 +01:00
{
2012-07-13 08:29:49 +02:00
// Report unmatched suppressions
2018-09-23 17:02:54 +02:00
for ( const Suppressions : : Suppression & s : unmatched ) {
2012-07-13 08:29:49 +02:00
// don't report "unmatchedSuppression" as unmatched
2018-09-23 17:02:54 +02:00
if ( s . errorId = = " unmatchedSuppression " )
2012-07-13 08:29:49 +02:00
continue ;
// check if this unmatched suppression is suppressed
bool suppressed = false ;
2018-09-23 17:02:54 +02:00
for ( const Suppressions : : Suppression & s2 : unmatched ) {
if ( s2 . errorId = = " unmatchedSuppression " ) {
if ( ( s2 . fileName = = " * " | | s2 . fileName = = s . fileName ) & &
( s2 . lineNumber = = Suppressions : : Suppression : : NO_LINE | | s2 . lineNumber = = s . lineNumber ) ) {
2012-07-13 08:29:49 +02:00
suppressed = true ;
2015-08-06 16:10:43 +02:00
break ;
}
2012-07-13 08:29:49 +02:00
}
}
if ( suppressed )
continue ;
2018-04-09 06:43:48 +02:00
std : : list < ErrorLogger : : ErrorMessage : : FileLocation > callStack ;
2018-09-23 17:02:54 +02:00
if ( ! s . fileName . empty ( ) )
2018-09-23 17:27:38 +02:00
callStack . emplace_back ( s . fileName , s . lineNumber ) ;
2018-09-23 17:02:54 +02:00
reportErr ( ErrorLogger : : ErrorMessage ( callStack , emptyString , Severity : : information , " Unmatched suppression: " + s . errorId , " unmatchedSuppression " , false ) ) ;
2011-02-16 02:12:15 +01:00
}
}
2009-07-10 22:38:26 +02:00
std : : string ErrorLogger : : callStackToString ( const std : : list < ErrorLogger : : ErrorMessage : : FileLocation > & callStack )
2009-02-09 21:51:04 +01:00
{
std : : ostringstream ostr ;
2011-10-13 20:53:06 +02:00
for ( std : : list < ErrorLogger : : ErrorMessage : : FileLocation > : : const_iterator tok = callStack . begin ( ) ; tok ! = callStack . end ( ) ; + + tok ) {
2012-05-06 10:17:15 +02:00
ostr < < ( tok = = callStack . begin ( ) ? " " : " -> " ) < < tok - > stringify ( ) ;
2011-02-16 02:12:15 +01:00
}
2009-02-09 21:51:04 +01:00
return ostr . str ( ) ;
2009-02-01 16:47:36 +01:00
}
2009-05-31 10:12:19 +02:00
2017-05-17 15:22:51 +02:00
ErrorLogger : : ErrorMessage : : FileLocation : : FileLocation ( const Token * tok , const TokenList * tokenList )
2018-06-17 07:52:59 +02:00
: fileIndex ( tok - > fileIndex ( ) ) , line ( tok - > linenr ( ) ) , col ( tok - > col ( ) ) , mFileName ( tokenList - > file ( tok ) )
2012-05-06 10:17:15 +02:00
{
}
2017-05-17 15:22:51 +02:00
ErrorLogger : : ErrorMessage : : FileLocation : : FileLocation ( const Token * tok , const std : : string & info , const TokenList * tokenList )
2018-06-17 07:52:59 +02:00
: fileIndex ( tok - > fileIndex ( ) ) , line ( tok - > linenr ( ) ) , col ( tok - > col ( ) ) , mFileName ( tokenList - > file ( tok ) ) , mInfo ( info )
2017-05-16 22:38:13 +02:00
{
}
2010-07-18 10:20:10 +02:00
std : : string ErrorLogger : : ErrorMessage : : FileLocation : : getfile ( bool convert ) const
2009-05-31 10:12:19 +02:00
{
2010-07-18 10:20:10 +02:00
if ( convert )
2018-06-17 07:52:59 +02:00
return Path : : toNativeSeparators ( mFileName ) ;
return mFileName ;
2009-05-31 10:12:19 +02:00
}
2010-07-17 00:27:40 +02:00
void ErrorLogger : : ErrorMessage : : FileLocation : : setfile ( const std : : string & file )
{
2018-06-17 07:52:59 +02:00
mFileName = file ;
mFileName = Path : : fromNativeSeparators ( mFileName ) ;
mFileName = Path : : simplifyPath ( mFileName ) ;
2010-07-17 00:27:40 +02:00
}
2012-05-06 10:17:15 +02:00
std : : string ErrorLogger : : ErrorMessage : : FileLocation : : stringify ( ) const
{
std : : ostringstream oss ;
2018-06-17 07:52:59 +02:00
oss < < ' [ ' < < Path : : toNativeSeparators ( mFileName ) ;
2018-09-18 12:58:14 +02:00
if ( line ! = Suppressions : : Suppression : : NO_LINE )
2012-05-06 10:17:15 +02:00
oss < < ' : ' < < line ;
oss < < ' ] ' ;
return oss . str ( ) ;
}
2015-12-07 18:11:13 +01:00
std : : string ErrorLogger : : toxml ( const std : : string & str )
{
std : : ostringstream xml ;
for ( std : : size_t i = 0U ; i < str . length ( ) ; i + + ) {
2018-05-29 13:24:48 +02:00
const unsigned char c = str [ i ] ;
2015-12-07 18:11:13 +01:00
switch ( c ) {
case ' < ' :
xml < < " < " ;
break ;
case ' > ' :
xml < < " > " ;
break ;
case ' & ' :
xml < < " & " ;
break ;
case ' \" ' :
xml < < " " " ;
break ;
case ' \0 ' :
xml < < " \\ 0 " ;
break ;
default :
2018-03-31 10:27:34 +02:00
if ( c > = ' ' & & c < = 0x7f )
2015-12-07 18:11:13 +01:00
xml < < c ;
else
xml < < ' x ' ;
break ;
}
}
return xml . str ( ) ;
}
2017-05-16 14:07:23 +02:00
std : : string ErrorLogger : : plistHeader ( const std : : string & version , const std : : vector < std : : string > & files )
{
std : : ostringstream ostr ;
ostr < < " <?xml version= \" 1.0 \" encoding= \" UTF-8 \" ?> \r \n "
< < " <!DOCTYPE plist PUBLIC \" -//Apple Computer//DTD PLIST 1.0//EN \" \" http://www.apple.com/DTDs/PropertyList-1.0.dtd \" > \r \n "
< < " <plist version= \" 1.0 \" > \r \n "
< < " <dict> \r \n "
< < " <key>clang_version</key> \r \n "
< < " <string>cppcheck version " < < version < < " </string> \r \n "
< < " <key>files</key> \r \n "
< < " <array> \r \n " ;
for ( unsigned int i = 0 ; i < files . size ( ) ; + + i )
ostr < < " <string> " < < ErrorLogger : : toxml ( files [ i ] ) < < " </string> \r \n " ;
ostr < < " </array> \r \n "
< < " <key>diagnostics</key> \r \n "
< < " <array> \r \n " ;
return ostr . str ( ) ;
}
static std : : string plistLoc ( const char indent [ ] , const ErrorLogger : : ErrorMessage : : FileLocation & loc )
{
std : : ostringstream ostr ;
ostr < < indent < < " <dict> \r \n "
< < indent < < ' ' < < " <key>line</key><integer> " < < loc . line < < " </integer> \r \n "
2017-05-17 15:22:51 +02:00
< < indent < < ' ' < < " <key>col</key><integer> " < < loc . col < < " </integer> \r \n "
< < indent < < ' ' < < " <key>file</key><integer> " < < loc . fileIndex < < " </integer> \r \n "
2017-05-16 14:07:23 +02:00
< < indent < < " </dict> \r \n " ;
return ostr . str ( ) ;
}
std : : string ErrorLogger : : plistData ( const ErrorLogger : : ErrorMessage & msg )
{
std : : ostringstream plist ;
plist < < " <dict> \r \n "
< < " <key>path</key> \r \n "
< < " <array> \r \n " ;
std : : list < ErrorLogger : : ErrorMessage : : FileLocation > : : const_iterator prev = msg . _callStack . begin ( ) ;
for ( std : : list < ErrorLogger : : ErrorMessage : : FileLocation > : : const_iterator it = msg . _callStack . begin ( ) ; it ! = msg . _callStack . end ( ) ; + + it ) {
if ( prev ! = it ) {
plist < < " <dict> \r \n "
< < " <key>kind</key><string>control</string> \r \n "
< < " <key>edges</key> \r \n "
< < " <array> \r \n "
< < " <dict> \r \n "
< < " <key>start</key> \r \n "
< < " <array> \r \n "
< < plistLoc ( " " , * prev )
< < plistLoc ( " " , * prev )
< < " </array> \r \n "
< < " <key>end</key> \r \n "
< < " <array> \r \n "
< < plistLoc ( " " , * it )
< < plistLoc ( " " , * it )
< < " </array> \r \n "
< < " </dict> \r \n "
< < " </array> \r \n "
< < " </dict> \r \n " ;
prev = it ;
}
std : : list < ErrorLogger : : ErrorMessage : : FileLocation > : : const_iterator next = it ;
+ + next ;
2017-05-17 15:22:51 +02:00
const std : : string message = ( it - > getinfo ( ) . empty ( ) & & next = = msg . _callStack . end ( ) ? msg . shortMessage ( ) : it - > getinfo ( ) ) ;
2017-05-16 14:07:23 +02:00
plist < < " <dict> \r \n "
< < " <key>kind</key><string>event</string> \r \n "
< < " <key>location</key> \r \n "
< < plistLoc ( " " , * it )
< < " <key>ranges</key> \r \n "
< < " <array> \r \n "
< < " <array> \r \n "
< < plistLoc ( " " , * it )
< < plistLoc ( " " , * it )
< < " </array> \r \n "
< < " </array> \r \n "
< < " <key>depth</key><integer>0</integer> \r \n "
< < " <key>extended_message</key> \r \n "
2017-05-17 15:22:51 +02:00
< < " <string> " < < ErrorLogger : : toxml ( message ) < < " </string> \r \n "
2017-05-16 14:07:23 +02:00
< < " <key>message</key> \r "
2017-05-17 15:22:51 +02:00
< < " <string> " < < ErrorLogger : : toxml ( message ) < < " </string> \r \n "
2017-05-16 14:07:23 +02:00
< < " </dict> \r \n " ;
}
plist < < " </array> \r \n "
< < " <key>description</key><string> " < < ErrorLogger : : toxml ( msg . shortMessage ( ) ) < < " </string> \r \n "
< < " <key>category</key><string> " < < Severity : : toString ( msg . _severity ) < < " </string> \r \n "
< < " <key>type</key><string> " < < ErrorLogger : : toxml ( msg . shortMessage ( ) ) < < " </string> \r \n "
< < " <key>check_name</key><string> " < < msg . _id < < " </string> \r \n "
< < " <!-- This hash is experimental and going to change! --> \r \n "
< < " <key>issue_hash_content_of_line_in_context</key><string> " < < 0 < < " </string> \r \n "
< < " <key>issue_context_kind</key><string></string> \r \n "
< < " <key>issue_context</key><string></string> \r \n "
< < " <key>issue_hash_function_offset</key><string></string> \r \n "
< < " <key>location</key> \r \n "
< < plistLoc ( " " , msg . _callStack . back ( ) )
< < " </dict> \r \n " ;
return plist . str ( ) ;
}