diff --git a/lib/check.h b/lib/check.h index 1a1138d3d..7ad86245c 100644 --- a/lib/check.h +++ b/lib/check.h @@ -33,6 +33,11 @@ /// @addtogroup Core /// @{ +struct CWE { + explicit CWE(unsigned short ID) : id(ID) {} + unsigned short id; +}; + /** * @brief Interface class that cppcheck uses to communicate with the checks. * All checking classes must inherit from this class @@ -111,12 +116,12 @@ protected: /** report an error */ template void reportError(const Token *tok, const Severity::SeverityType severity, const T id, const U msg) { - reportError(tok, severity, id, msg, 0U, false); + reportError(tok, severity, id, msg, CWE(0U), false); } /** report an error */ template - void reportError(const Token *tok, const Severity::SeverityType severity, const T id, const U msg, unsigned int cwe, bool inconclusive) { + void reportError(const Token *tok, const Severity::SeverityType severity, const T id, const U msg, const CWE &cwe, bool inconclusive) { std::list callstack(1, tok); reportError(callstack, severity, id, msg, cwe, inconclusive); } @@ -124,14 +129,14 @@ protected: /** report an error */ template void reportError(const std::list &callstack, Severity::SeverityType severity, const T id, const U msg) { - reportError(callstack, severity, id, msg, 0U, false); + reportError(callstack, severity, id, msg, CWE(0U), false); } /** report an error */ template - void reportError(const std::list &callstack, Severity::SeverityType severity, const T id, const U msg, unsigned int cwe, bool inconclusive) { + void reportError(const std::list &callstack, Severity::SeverityType severity, const T id, const U msg, const CWE &cwe, bool inconclusive) { ErrorLogger::ErrorMessage errmsg(callstack, _tokenizer?&_tokenizer->list:0, severity, id, msg, inconclusive); - errmsg._cwe = cwe; + errmsg._cwe = cwe.id; if (_errorLogger) _errorLogger->reportErr(errmsg); else diff --git a/lib/checkautovariables.cpp b/lib/checkautovariables.cpp index 2a60d433e..7f3f22a3c 100644 --- a/lib/checkautovariables.cpp +++ b/lib/checkautovariables.cpp @@ -33,6 +33,8 @@ namespace { static CheckAutoVariables instance; } +static const CWE CWE562(562U); +static const CWE CWE590(590U); bool CheckAutoVariables::isPtrArg(const Token *tok) { @@ -287,12 +289,12 @@ void CheckAutoVariables::returnPointerToLocalArray() void CheckAutoVariables::errorReturnAddressToAutoVariable(const Token *tok) { - reportError(tok, Severity::error, "returnAddressOfAutoVariable", "Address of an auto-variable returned.", 562U, false); + reportError(tok, Severity::error, "returnAddressOfAutoVariable", "Address of an auto-variable returned.", CWE562, false); } void CheckAutoVariables::errorReturnPointerToLocalArray(const Token *tok) { - reportError(tok, Severity::error, "returnLocalVariable", "Pointer to local array variable returned.", 562, false); + reportError(tok, Severity::error, "returnLocalVariable", "Pointer to local array variable returned.", CWE562, false); } void CheckAutoVariables::errorAutoVariableAssignment(const Token *tok, bool inconclusive) @@ -303,7 +305,7 @@ void CheckAutoVariables::errorAutoVariableAssignment(const Token *tok, bool inco "Dangerous assignment - the function parameter is assigned the address of a local " "auto-variable. Local auto-variables are reserved from the stack which " "is freed when the function ends. So the pointer to a local variable " - "is invalid after the function ends.", 562U, false); + "is invalid after the function ends.", CWE562, false); } else { reportError(tok, Severity::error, "autoVariables", "Address of local auto-variable assigned to a function parameter.\n" @@ -311,7 +313,7 @@ void CheckAutoVariables::errorAutoVariableAssignment(const Token *tok, bool inco "Local auto-variables are reserved from the stack which is freed when " "the function ends. The address is invalid after the function ends and it " "might 'leak' from the function through the parameter.", - 562U, + CWE562, true); } } @@ -322,7 +324,7 @@ void CheckAutoVariables::errorReturnAddressOfFunctionParameter(const Token *tok, "Address of function parameter '" + varname + "' returned.\n" "Address of the function parameter '" + varname + "' becomes invalid after the function exits because " "function parameters are stored on the stack which is freed when the function exits. Thus the returned " - "value is invalid.", 562U, false); + "value is invalid.", CWE562, false); } void CheckAutoVariables::errorUselessAssignmentArg(const Token *tok) @@ -492,12 +494,12 @@ void CheckAutoVariables::returnReference() void CheckAutoVariables::errorReturnReference(const Token *tok) { - reportError(tok, Severity::error, "returnReference", "Reference to auto variable returned.", 562U, false); + reportError(tok, Severity::error, "returnReference", "Reference to auto variable returned.", CWE562, false); } void CheckAutoVariables::errorReturnTempReference(const Token *tok) { - reportError(tok, Severity::error, "returnTempReference", "Reference to temporary returned.", 562U, false); + reportError(tok, Severity::error, "returnTempReference", "Reference to temporary returned.", CWE562, false); } void CheckAutoVariables::errorInvalidDeallocation(const Token *tok) @@ -507,5 +509,5 @@ void CheckAutoVariables::errorInvalidDeallocation(const Token *tok) "autovarInvalidDeallocation", "Deallocation of an auto-variable results in undefined behaviour.\n" "The deallocation of an auto-variable results in undefined behaviour. You should only free memory " - "that has been allocated dynamically.", 590U, false); + "that has been allocated dynamically.", CWE590, false); } diff --git a/lib/checkbool.cpp b/lib/checkbool.cpp index cd948c34a..17a4a13ea 100644 --- a/lib/checkbool.cpp +++ b/lib/checkbool.cpp @@ -28,6 +28,8 @@ namespace { CheckBool instance; } +static const CWE CWE571(571); +static const CWE CWE587(587); static bool astIsBool(const Token *expr) { @@ -106,7 +108,7 @@ void CheckBool::bitwiseOnBooleanError(const Token *tok, const std::string &varna { reportError(tok, Severity::style, "bitwiseOnBoolean", "Boolean variable '" + varname + "' is used in bitwise operation. Did you mean '" + op + "'?", - 0U, + CWE(0), true); } @@ -352,7 +354,7 @@ void CheckBool::checkAssignBoolToPointer() void CheckBool::assignBoolToPointerError(const Token *tok) { reportError(tok, Severity::error, "assignBoolToPointer", - "Boolean value assigned to pointer.", 587U, false); + "Boolean value assigned to pointer.", CWE587, false); } //----------------------------------------------------------------------------- @@ -473,7 +475,7 @@ void CheckBool::pointerArithBoolError(const Token *tok) Severity::error, "pointerArithBool", "Converting pointer arithmetic result to bool. The bool is always true unless there is undefined behaviour.\n" - "Converting pointer arithmetic result to bool. The boolean result is always true unless there is pointer arithmetic overflow, and overflow is undefined behaviour. Probably a dereference is forgotten.", 571U, false); + "Converting pointer arithmetic result to bool. The boolean result is always true unless there is pointer arithmetic overflow, and overflow is undefined behaviour. Probably a dereference is forgotten.", CWE571, false); } void CheckBool::checkAssignBoolToFloat() diff --git a/lib/checkboost.cpp b/lib/checkboost.cpp index ea27afb70..7336e5a19 100644 --- a/lib/checkboost.cpp +++ b/lib/checkboost.cpp @@ -24,6 +24,8 @@ namespace { CheckBoost instance; } +static const CWE CWE664(664); + void CheckBoost::checkBoostForeachModification() { const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase(); @@ -55,6 +57,6 @@ void CheckBoost::checkBoostForeachModification() void CheckBoost::boostForeachError(const Token *tok) { reportError(tok, Severity::error, "boostForeachError", - "BOOST_FOREACH caches the end() iterator. It's undefined behavior if you modify the container inside.", 664U, false + "BOOST_FOREACH caches the end() iterator. It's undefined behavior if you modify the container inside.", CWE664, false ); } diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp index a1320bf5e..693f920a5 100644 --- a/lib/checkbufferoverrun.cpp +++ b/lib/checkbufferoverrun.cpp @@ -43,6 +43,13 @@ namespace { //--------------------------------------------------------------------------- +// CWE ids used: +static const CWE CWE119(119U); +static const CWE CWE131(131U); +static const CWE CWE788(788U); + +//--------------------------------------------------------------------------- + static void makeArrayIndexOutOfBoundsError(std::ostream& oss, const CheckBufferOverrun::ArrayInfo &arrayInfo, const std::vector &index) { oss << "Array '" << arrayInfo.varname(); @@ -61,7 +68,7 @@ void CheckBufferOverrun::arrayIndexOutOfBoundsError(const Token *tok, const Arra { std::ostringstream oss; makeArrayIndexOutOfBoundsError(oss, arrayInfo, index); - reportError(tok, Severity::error, "arrayIndexOutOfBounds", oss.str(), 788U, false); + reportError(tok, Severity::error, "arrayIndexOutOfBounds", oss.str(), CWE788, false); } void CheckBufferOverrun::arrayIndexOutOfBoundsError(const Token *tok, const ArrayInfo &arrayInfo, const std::vector &index) @@ -92,7 +99,7 @@ void CheckBufferOverrun::arrayIndexOutOfBoundsError(const Token *tok, const Arra std::list callstack; callstack.push_back(tok); callstack.push_back(condition); - reportError(callstack, Severity::warning, "arrayIndexOutOfBoundsCond", errmsg.str(), 0U, false); + reportError(callstack, Severity::warning, "arrayIndexOutOfBoundsCond", errmsg.str(), CWE(0U), false); } else { std::ostringstream errmsg; errmsg << "Array '" << arrayInfo.varname(); @@ -133,7 +140,7 @@ static std::string bufferOverrunMessage(std::string varnames) void CheckBufferOverrun::bufferOverrunError(const Token *tok, const std::string &varnames) { - reportError(tok, Severity::error, "bufferAccessOutOfBounds", bufferOverrunMessage(varnames), 788U, false); + reportError(tok, Severity::error, "bufferAccessOutOfBounds", bufferOverrunMessage(varnames), CWE788, false); } @@ -177,7 +184,7 @@ void CheckBufferOverrun::outOfBoundsError(const Token *tok, const std::string &w if (show_size_info) oss << ": Supplied size " << supplied_size << " is larger than actual size " << actual_size; oss << '.'; - reportError(tok, Severity::error, "outOfBounds", oss.str(), 788U, false); + reportError(tok, Severity::error, "outOfBounds", oss.str(), CWE788, false); } void CheckBufferOverrun::pointerOutOfBoundsError(const Token *tok, const Token *index, const MathLib::bigint indexvalue) @@ -221,12 +228,12 @@ void CheckBufferOverrun::terminateStrncpyError(const Token *tok, const std::stri "The buffer '" + varname + "' may not be null-terminated after the call to strncpy().\n" "If the source string's size fits or exceeds the given size, strncpy() does not add a " "zero at the end of the buffer. This causes bugs later in the code if the code " - "assumes buffer is null-terminated.", 0U, true); + "assumes buffer is null-terminated.", CWE(0U), true); } void CheckBufferOverrun::cmdLineArgsError(const Token *tok) { - reportError(tok, Severity::error, "insecureCmdLineArgs", "Buffer overrun possible for long command line arguments.", 119U, false); + reportError(tok, Severity::error, "insecureCmdLineArgs", "Buffer overrun possible for long command line arguments.", CWE119, false); } void CheckBufferOverrun::bufferNotZeroTerminatedError(const Token *tok, const std::string &varname, const std::string &function) @@ -235,7 +242,7 @@ void CheckBufferOverrun::bufferNotZeroTerminatedError(const Token *tok, const st "The buffer '" + varname + "' is not null-terminated after the call to " + function + "(). " "This will cause bugs later in the code if the code assumes the buffer is null-terminated."; - reportError(tok, Severity::warning, "bufferNotZeroTerminated", errmsg, 0U, true); + reportError(tok, Severity::warning, "bufferNotZeroTerminated", errmsg, CWE(0U), true); } void CheckBufferOverrun::argumentSizeError(const Token *tok, const std::string &functionName, const std::string &varname) @@ -248,7 +255,7 @@ void CheckBufferOverrun::negativeMemoryAllocationSizeError(const Token *tok) reportError(tok, Severity::error, "negativeMemoryAllocationSize", "Memory allocation size is negative.\n" "Memory allocation size is negative." - "Negative allocation size has no specified behaviour.", 131U, false); + "Negative allocation size has no specified behaviour.", CWE131, false); } //--------------------------------------------------------------------------- @@ -1717,7 +1724,7 @@ void CheckBufferOverrun::negativeIndexError(const Token *tok, const ValueFlow::V ostr << "Array index " << index.intvalue << " is out of bounds."; if (index.condition) ostr << " Otherwise there is useless condition at line " << index.condition->linenr() << "."; - reportError(tok, index.condition ? Severity::warning : Severity::error, "negativeIndex", ostr.str(), 0U, index.inconclusive); + reportError(tok, index.condition ? Severity::warning : Severity::error, "negativeIndex", ostr.str(), CWE(0U), index.inconclusive); } CheckBufferOverrun::ArrayInfo::ArrayInfo() diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 2acc3183e..c4e8f9fa0 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -33,31 +33,35 @@ // Register CheckClass.. namespace { CheckClass instance; +} - const char * getFunctionTypeName( - Function::Type type) - { - switch (type) { - case Function::eConstructor: - return "constructor"; - case Function::eCopyConstructor: - return "copy constructor"; - case Function::eMoveConstructor: - return "move constructor"; - case Function::eDestructor: - return "destructor"; - case Function::eFunction: - return "function"; - case Function::eOperatorEqual: - return "operator="; - } - return ""; - } +static const CWE CWE404(404U); +static const CWE CWE665(665U); +static const CWE CWE762(762U); - inline bool isPureWithoutBody(Function const & func) - { - return func.isPure() && !func.hasBody(); +static const char * getFunctionTypeName( + Function::Type type) +{ + switch (type) { + case Function::eConstructor: + return "constructor"; + case Function::eCopyConstructor: + return "copy constructor"; + case Function::eMoveConstructor: + return "move constructor"; + case Function::eDestructor: + return "destructor"; + case Function::eFunction: + return "function"; + case Function::eOperatorEqual: + return "operator="; } + return ""; +} + +static bool isPureWithoutBody(Function const & func) +{ + return func.isPure() && !func.hasBody(); } //--------------------------------------------------------------------------- @@ -788,12 +792,12 @@ void CheckClass::noExplicitConstructorError(const Token *tok, const std::string void CheckClass::uninitVarError(const Token *tok, const std::string &classname, const std::string &varname, bool inconclusive) { - reportError(tok, Severity::warning, "uninitMemberVar", "Member variable '" + classname + "::" + varname + "' is not initialized in the constructor.", 0U, inconclusive); + reportError(tok, Severity::warning, "uninitMemberVar", "Member variable '" + classname + "::" + varname + "' is not initialized in the constructor.", CWE(0U), inconclusive); } void CheckClass::operatorEqVarError(const Token *tok, const std::string &classname, const std::string &varname, bool inconclusive) { - reportError(tok, Severity::warning, "operatorEqVarError", "Member variable '" + classname + "::" + varname + "' is not assigned a value in '" + classname + "::operator='.", 0U, inconclusive); + reportError(tok, Severity::warning, "operatorEqVarError", "Member variable '" + classname + "::" + varname + "' is not assigned a value in '" + classname + "::operator='.", CWE(0U), inconclusive); } //--------------------------------------------------------------------------- @@ -1133,7 +1137,7 @@ void CheckClass::mallocOnClassWarning(const Token* tok, const std::string &memfu reportError(toks, Severity::warning, "mallocOnClassWarning", "Memory for class instance allocated with " + memfunc + "(), but class provides constructors.\n" "Memory for class instance allocated with " + memfunc + "(), but class provides constructors. This is unsafe, " - "since no constructor is called and class members remain uninitialized. Consider using 'new' instead.", 0U, false); + "since no constructor is called and class members remain uninitialized. Consider using 'new' instead.", CWE(0U), false); } void CheckClass::mallocOnClassError(const Token* tok, const std::string &memfunc, const Token* classTok, const std::string &classname) @@ -1144,7 +1148,7 @@ void CheckClass::mallocOnClassError(const Token* tok, const std::string &memfunc reportError(toks, Severity::error, "mallocOnClassError", "Memory for class instance allocated with " + memfunc + "(), but class contains a " + classname + ".\n" "Memory for class instance allocated with " + memfunc + "(), but class a " + classname + ". This is unsafe, " - "since no constructor is called and class members remain uninitialized. Consider using 'new' instead.", 665U, false); + "since no constructor is called and class members remain uninitialized. Consider using 'new' instead.", CWE665, false); } void CheckClass::memsetError(const Token *tok, const std::string &memfunc, const std::string &classname, const std::string &type) @@ -1153,12 +1157,12 @@ void CheckClass::memsetError(const Token *tok, const std::string &memfunc, const "Using '" + memfunc + "' on " + type + " that contains a " + classname + ".\n" "Using '" + memfunc + "' on " + type + " that contains a " + classname + " is unsafe, because constructor, destructor " "and copy operator calls are omitted. These are necessary for this non-POD type to ensure that a valid object " - "is created.", 762U, false); + "is created.", CWE762, false); } void CheckClass::memsetErrorReference(const Token *tok, const std::string &memfunc, const std::string &type) { - reportError(tok, Severity::error, "memsetClassReference", "Using '" + memfunc + "' on " + type + " that contains a reference.", 665U, false); + reportError(tok, Severity::error, "memsetClassReference", "Using '" + memfunc + "' on " + type + " that contains a reference.", CWE665, false); } void CheckClass::memsetErrorFloat(const Token *tok, const std::string &type) @@ -1614,7 +1618,7 @@ void CheckClass::virtualDestructor() void CheckClass::virtualDestructorError(const Token *tok, const std::string &Base, const std::string &Derived, bool inconclusive) { if (inconclusive) - reportError(tok, Severity::warning, "virtualDestructor", "Class '" + Base + "' which has virtual members does not have a virtual destructor.", 404U, true); + reportError(tok, Severity::warning, "virtualDestructor", "Class '" + Base + "' which has virtual members does not have a virtual destructor.", CWE404, true); else reportError(tok, Severity::error, "virtualDestructor", "Class '" + Base + "' which is inherited by class '" + Derived + "' does not have a virtual destructor.\n" "Class '" + Base + "' which is inherited by class '" + Derived + "' does not have a virtual destructor. " @@ -1988,7 +1992,7 @@ void CheckClass::checkConstError2(const Token *tok1, const Token *tok2, const st "function. Making this function 'const' should not cause compiler errors. " "Even though the function can be made const function technically it may not make " "sense conceptually. Think about your design and the task of the function first - is " - "it a function that must not change object internal state?", 0U, true); + "it a function that must not change object internal state?", CWE(0U), true); else reportError(toks, Severity::performance, "functionStatic", "Technically the member function '" + classname + "::" + funcname + "' can be static.\n" @@ -1996,7 +2000,7 @@ void CheckClass::checkConstError2(const Token *tok1, const Token *tok2, const st "function. Making a function static can bring a performance benefit since no 'this' instance is " "passed to the function. This change should not cause compiler errors but it does not " "necessarily make sense conceptually. Think about your design and the task of the function first - " - "is it a function that must not access members of class instances?", 0U, true); + "is it a function that must not access members of class instances?", CWE(0U), true); } //--------------------------------------------------------------------------- @@ -2083,7 +2087,7 @@ void CheckClass::initializerListError(const Token *tok1, const Token *tok2, cons "Members are initialized in the order they are declared, not in the " "order they are in the initializer list. Keeping the initializer list " "in the same order that the members were declared prevents order dependent " - "initialization errors.", 0U, true); + "initialization errors.", CWE(0U), true); } @@ -2113,7 +2117,7 @@ void CheckClass::checkSelfInitialization() void CheckClass::selfInitializationError(const Token* tok, const std::string& varname) { - reportError(tok, Severity::error, "selfInitialization", "Member variable '" + varname + "' is initialized by itself.", 665U, false); + reportError(tok, Severity::error, "selfInitialization", "Member variable '" + varname + "' is initialized by itself.", CWE665, false); } @@ -2235,7 +2239,7 @@ void CheckClass::callsPureVirtualFunctionError( { const char * scopeFunctionTypeName = getFunctionTypeName(scopeFunction.type); reportError(tokStack, Severity::warning, "pureVirtualCall", "Call of pure virtual function '" + purefuncname + "' in " + scopeFunctionTypeName + ".\n" - "Call of pure virtual function '" + purefuncname + "' in " + scopeFunctionTypeName + ". The call will fail during runtime.", 0U, false); + "Call of pure virtual function '" + purefuncname + "' in " + scopeFunctionTypeName + ". The call will fail during runtime.", CWE(0U), false); } @@ -2289,5 +2293,5 @@ void CheckClass::duplInheritedMembersError(const Token *tok1, const Token* tok2, const std::string message = "The " + std::string(derivedIsStruct ? "struct" : "class") + " '" + derivedname + "' defines member variable with name '" + variablename + "' also defined in its parent " + std::string(baseIsStruct ? "struct" : "class") + " '" + basename + "'."; - reportError(toks, Severity::warning, "duplInheritedMember", message, 0U, false); + reportError(toks, Severity::warning, "duplInheritedMember", message, CWE(0U), false); } diff --git a/lib/checkexceptionsafety.h b/lib/checkexceptionsafety.h index 1e22b4080..20d5c731e 100644 --- a/lib/checkexceptionsafety.h +++ b/lib/checkexceptionsafety.h @@ -122,7 +122,7 @@ private: reportError(locationList, Severity::style, "unhandledExceptionSpecification", "Unhandled exception specification when calling function " + str1 + "().\n" "Unhandled exception specification when calling function " + str1 + "(). " - "Either use a try/catch around the function call, or add a exception specification for " + funcname + "() also.", 0U, true); + "Either use a try/catch around the function call, or add a exception specification for " + funcname + "() also.", CWE(0U), true); } /** Generate all possible errors (for --errorlist) */ diff --git a/lib/checkfunctions.cpp b/lib/checkfunctions.cpp index 171e82eca..21756a8d6 100644 --- a/lib/checkfunctions.cpp +++ b/lib/checkfunctions.cpp @@ -32,6 +32,8 @@ namespace { CheckFunctions instance; } +static const CWE CWE628(628U); + void CheckFunctions::checkProhibitedFunctions() { const bool checkAlloca = _settings->isEnabled("warning") && ((_settings->standards.c >= Standards::C99 && _tokenizer->isC()) || _settings->standards.cpp >= Standards::CPP11); @@ -127,14 +129,14 @@ void CheckFunctions::invalidFunctionArgError(const Token *tok, const std::string errmsg << ". The value is " << tok->str() << " but the valid values are '" << validstr << "'."; else if (tok->isComparisonOp()) errmsg << ". The value is 0 or 1 (comparison result) but the valid values are '" << validstr << "'."; - reportError(tok, Severity::error, "invalidFunctionArg", errmsg.str(), 628U, false); + reportError(tok, Severity::error, "invalidFunctionArg", errmsg.str(), CWE628, false); } void CheckFunctions::invalidFunctionArgBoolError(const Token *tok, const std::string &functionName, int argnr) { std::ostringstream errmsg; errmsg << "Invalid " << functionName << "() argument nr " << argnr << ". A non-boolean value is required."; - reportError(tok, Severity::error, "invalidFunctionArgBool", errmsg.str(), 628U, false); + reportError(tok, Severity::error, "invalidFunctionArgBool", errmsg.str(), CWE628, false); } //--------------------------------------------------------------------------- @@ -173,7 +175,7 @@ void CheckFunctions::checkIgnoredReturnValue() void CheckFunctions::ignoredReturnValueError(const Token* tok, const std::string& function) { reportError(tok, Severity::warning, "ignoredReturnValue", - "Return value of function " + function + "() is not used.", 0U, false); + "Return value of function " + function + "() is not used.", CWE(0U), false); } diff --git a/lib/checkio.cpp b/lib/checkio.cpp index d611f2922..bf9e144c9 100644 --- a/lib/checkio.cpp +++ b/lib/checkio.cpp @@ -33,6 +33,10 @@ namespace { CheckIO instance; } +static const CWE CWE664(664U); +static const CWE CWE685(685U); +static const CWE CWE687(687U); +static const CWE CWE910(910U); //--------------------------------------------------------------------------- // std::cout << std::cout; @@ -335,26 +339,26 @@ void CheckIO::fflushOnInputStreamError(const Token *tok, const std::string &varn void CheckIO::ioWithoutPositioningError(const Token *tok) { reportError(tok, Severity::error, - "IOWithoutPositioning", "Read and write operations without a call to a positioning function (fseek, fsetpos or rewind) or fflush in between result in undefined behaviour.", 664U, false); + "IOWithoutPositioning", "Read and write operations without a call to a positioning function (fseek, fsetpos or rewind) or fflush in between result in undefined behaviour.", CWE664, false); } void CheckIO::readWriteOnlyFileError(const Token *tok) { reportError(tok, Severity::error, - "readWriteOnlyFile", "Read operation on a file that was opened only for writing.", 664U, false); + "readWriteOnlyFile", "Read operation on a file that was opened only for writing.", CWE664, false); } void CheckIO::writeReadOnlyFileError(const Token *tok) { reportError(tok, Severity::error, - "writeReadOnlyFile", "Write operation on a file that was opened only for reading.", 664U, false); + "writeReadOnlyFile", "Write operation on a file that was opened only for reading.", CWE664, false); } void CheckIO::useClosedFileError(const Token *tok) { reportError(tok, Severity::error, - "useClosedFile", "Used file that is not opened.", 910U, false); + "useClosedFile", "Used file that is not opened.", CWE910, false); } void CheckIO::seekOnAppendedFileError(const Token *tok) @@ -1715,7 +1719,7 @@ void CheckIO::wrongPrintfScanfArgumentsError(const Token* tok, << (numFunction != 1 ? " are" : " is") << " given."; - reportError(tok, severity, "wrongPrintfScanfArgNum", errmsg.str(), 685U, false); + reportError(tok, severity, "wrongPrintfScanfArgNum", errmsg.str(), CWE685, false); } void CheckIO::wrongPrintfScanfPosixParameterPositionError(const Token* tok, const std::string& functionName, @@ -1998,10 +2002,10 @@ void CheckIO::invalidScanfFormatWidthError(const Token* tok, unsigned int numFor return; errmsg << "Width " << width << " given in format string (no. " << numFormat << ") is smaller than destination buffer" << " '" << varname << "[" << arrlen << "]'."; - reportError(tok, Severity::warning, "invalidScanfFormatWidth_smaller", errmsg.str(), 0U, true); + reportError(tok, Severity::warning, "invalidScanfFormatWidth_smaller", errmsg.str(), CWE(0U), true); } else { errmsg << "Width " << width << " given in format string (no. " << numFormat << ") is larger than destination buffer '" << varname << "[" << arrlen << "]', use %" << (arrlen - 1) << "s to prevent overflowing it."; - reportError(tok, Severity::error, "invalidScanfFormatWidth", errmsg.str(), 687U, false); + reportError(tok, Severity::error, "invalidScanfFormatWidth", errmsg.str(), CWE687, false); } } diff --git a/lib/checkleakautovar.cpp b/lib/checkleakautovar.cpp index daf3ec6e3..4a35a2d02 100644 --- a/lib/checkleakautovar.cpp +++ b/lib/checkleakautovar.cpp @@ -35,6 +35,8 @@ namespace { CheckLeakAutoVar instance; } +static const CWE CWE672(672U); +static const CWE CWE415(415U); //--------------------------------------------------------------------------- void VarInfo::print() @@ -85,7 +87,7 @@ void CheckLeakAutoVar::deallocUseError(const Token *tok, const std::string &varn void CheckLeakAutoVar::deallocReturnError(const Token *tok, const std::string &varname) { - reportError(tok, Severity::error, "deallocret", "Returning/dereferencing '" + varname + "' after it is deallocated / released", 672U, false); + reportError(tok, Severity::error, "deallocret", "Returning/dereferencing '" + varname + "' after it is deallocated / released", CWE672, false); } void CheckLeakAutoVar::configurationInfo(const Token* tok, const std::string &functionName) @@ -101,9 +103,9 @@ void CheckLeakAutoVar::configurationInfo(const Token* tok, const std::string &fu void CheckLeakAutoVar::doubleFreeError(const Token *tok, const std::string &varname, int type) { if (_settings->library.isresource(type)) - reportError(tok, Severity::error, "doubleFree", "Resource handle '" + varname + "' freed twice.", 415U, false); + reportError(tok, Severity::error, "doubleFree", "Resource handle '" + varname + "' freed twice.", CWE415, false); else - reportError(tok, Severity::error, "doubleFree", "Memory pointed to by '" + varname + "' is freed twice.", 415U, false); + reportError(tok, Severity::error, "doubleFree", "Memory pointed to by '" + varname + "' is freed twice.", CWE415, false); } diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index cf383280a..8d38c7fbb 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -36,47 +36,50 @@ namespace { CheckMemoryLeakInClass instance2; CheckMemoryLeakStructMember instance3; CheckMemoryLeakNoVar instance4; - - /** - * Count function parameters - * \param tok Function name token before the '(' - */ - unsigned int countParameters(const Token *tok) - { - tok = tok->tokAt(2); - if (tok->str() == ")") - return 0; - - unsigned int numpar = 1; - while (nullptr != (tok = tok->nextArgument())) - numpar++; - - return numpar; - } - - - /** List of functions that can be ignored when searching for memory leaks. - * These functions don't take the address of the given pointer - * This list contains function names with const parameters e.g.: atof(const char *) - * TODO: This list should be replaced by in .cfg files. - */ - const std::set call_func_white_list = make_container < std::set > () - << "_open" << "_wopen" << "access" << "adjtime" << "asctime_r" << "asprintf" << "chdir" << "chmod" << "chown" - << "creat" << "ctime_r" << "execl" << "execle" << "execlp" << "execv" << "execve" << "fchmod" << "fcntl" - << "fdatasync" << "fclose" << "flock" << "fmemopen" << "fnmatch" << "fopen" << "fopencookie" << "for" << "free" - << "freopen"<< "fseeko" << "fstat" << "fsync" << "ftello" << "ftruncate" << "getgrnam" << "gethostbyaddr" << "gethostbyname" - << "getnetbyname" << "getopt" << "getopt_long" << "getprotobyname" << "getpwnam" << "getservbyname" << "getservbyport" - << "glob" << "gmtime" << "gmtime_r" << "if" << "index" << "inet_addr" << "inet_aton" << "inet_network" << "initgroups" - << "ioctl" << "link" << "localtime_r" << "lockf" << "lseek" << "lstat" << "mkdir" << "mkfifo" << "mknod" << "mkstemp" - << "obstack_printf" << "obstack_vprintf" << "open" << "opendir" << "parse_printf_format" << "pathconf" - << "perror" << "popen" << "posix_fadvise" << "posix_fallocate" << "pread" << "psignal" << "pwrite" << "read" << "readahead" - << "readdir" << "readdir_r" << "readlink" << "readv" << "realloc" << "regcomp" << "return" << "rewinddir" << "rindex" - << "rmdir" << "scandir" << "seekdir" << "setbuffer" << "sethostname" << "setlinebuf" << "sizeof" << "strdup" - << "stat" << "stpcpy" << "strcasecmp" << "stricmp" << "strncasecmp" << "switch" - << "symlink" << "sync_file_range" << "telldir" << "tempnam" << "time" << "typeid" << "unlink" - << "utime" << "utimes" << "vasprintf" << "while" << "wordexp" << "write" << "writev"; } +static const CWE CWE771(771U); +static const CWE CWE772(772U); + +/** + * Count function parameters + * \param tok Function name token before the '(' + */ +static unsigned int countParameters(const Token *tok) +{ + tok = tok->tokAt(2); + if (tok->str() == ")") + return 0; + + unsigned int numpar = 1; + while (nullptr != (tok = tok->nextArgument())) + numpar++; + + return numpar; +} + + +/** List of functions that can be ignored when searching for memory leaks. + * These functions don't take the address of the given pointer + * This list contains function names with const parameters e.g.: atof(const char *) + * TODO: This list should be replaced by in .cfg files. + */ +static const std::set call_func_white_list = make_container < std::set > () + << "_open" << "_wopen" << "access" << "adjtime" << "asctime_r" << "asprintf" << "chdir" << "chmod" << "chown" + << "creat" << "ctime_r" << "execl" << "execle" << "execlp" << "execv" << "execve" << "fchmod" << "fcntl" + << "fdatasync" << "fclose" << "flock" << "fmemopen" << "fnmatch" << "fopen" << "fopencookie" << "for" << "free" + << "freopen"<< "fseeko" << "fstat" << "fsync" << "ftello" << "ftruncate" << "getgrnam" << "gethostbyaddr" << "gethostbyname" + << "getnetbyname" << "getopt" << "getopt_long" << "getprotobyname" << "getpwnam" << "getservbyname" << "getservbyport" + << "glob" << "gmtime" << "gmtime_r" << "if" << "index" << "inet_addr" << "inet_aton" << "inet_network" << "initgroups" + << "ioctl" << "link" << "localtime_r" << "lockf" << "lseek" << "lstat" << "mkdir" << "mkfifo" << "mknod" << "mkstemp" + << "obstack_printf" << "obstack_vprintf" << "open" << "opendir" << "parse_printf_format" << "pathconf" + << "perror" << "popen" << "posix_fadvise" << "posix_fallocate" << "pread" << "psignal" << "pwrite" << "read" << "readahead" + << "readdir" << "readdir_r" << "readlink" << "readv" << "realloc" << "regcomp" << "return" << "rewinddir" << "rindex" + << "rmdir" << "scandir" << "seekdir" << "setbuffer" << "sethostname" << "setlinebuf" << "sizeof" << "strdup" + << "stat" << "stpcpy" << "strcasecmp" << "stricmp" << "strncasecmp" << "switch" + << "symlink" << "sync_file_range" << "telldir" << "tempnam" << "time" << "typeid" << "unlink" + << "utime" << "utimes" << "vasprintf" << "while" << "wordexp" << "write" << "writev"; + //--------------------------------------------------------------------------- bool CheckMemoryLeak::isclass(const Token *tok, unsigned int varid) const @@ -2715,12 +2718,12 @@ void CheckMemoryLeakNoVar::checkForUnsafeArgAlloc(const Scope *scope) void CheckMemoryLeakNoVar::functionCallLeak(const Token *loc, const std::string &alloc, const std::string &functionCall) { - reportError(loc, Severity::error, "leakNoVarFunctionCall", "Allocation with " + alloc + ", " + functionCall + " doesn't release it.", 772U, false); + reportError(loc, Severity::error, "leakNoVarFunctionCall", "Allocation with " + alloc + ", " + functionCall + " doesn't release it.", CWE772, false); } void CheckMemoryLeakNoVar::returnValueNotUsedError(const Token *tok, const std::string &alloc) { - reportError(tok, Severity::error, "leakReturnValNotUsed", "Return value of allocation function '" + alloc + "' is not stored.", 771U, false); + reportError(tok, Severity::error, "leakReturnValNotUsed", "Return value of allocation function '" + alloc + "' is not stored.", CWE771, false); } void CheckMemoryLeakNoVar::unsafeArgAllocError(const Token *tok, const std::string &funcName, const std::string &ptrType, const std::string& objType) @@ -2728,6 +2731,6 @@ void CheckMemoryLeakNoVar::unsafeArgAllocError(const Token *tok, const std::stri const std::string factoryFunc = ptrType == "shared_ptr" ? "make_shared" : "make_unique"; reportError(tok, Severity::warning, "leakUnsafeArgAlloc", "Unsafe allocation. If " + funcName + "() throws, memory could be leaked. Use " + factoryFunc + "<" + objType + ">() instead.", - 0U, + CWE(0U), true); // Inconclusive because funcName may never throw } diff --git a/lib/checknullpointer.cpp b/lib/checknullpointer.cpp index 9d42f50e1..b375c402d 100644 --- a/lib/checknullpointer.cpp +++ b/lib/checknullpointer.cpp @@ -30,6 +30,8 @@ namespace { CheckNullPointer instance; } +static const CWE CWE476(476U); + //--------------------------------------------------------------------------- static bool checkNullpointerFunctionCallPlausibility(const Function* func, unsigned int arg) @@ -466,16 +468,16 @@ void CheckNullPointer::nullConstantDereference() void CheckNullPointer::nullPointerError(const Token *tok) { - reportError(tok, Severity::error, "nullPointer", "Null pointer dereference", 476U, false); + reportError(tok, Severity::error, "nullPointer", "Null pointer dereference", CWE476, false); } void CheckNullPointer::nullPointerError(const Token *tok, const std::string &varname, bool inconclusive, bool defaultArg) { if (defaultArg) { if (_settings->isEnabled("warning")) - reportError(tok, Severity::warning, "nullPointerDefaultArg", "Possible null pointer dereference if the default parameter value is used: " + varname, 0U, inconclusive); + reportError(tok, Severity::warning, "nullPointerDefaultArg", "Possible null pointer dereference if the default parameter value is used: " + varname, CWE(0U), inconclusive); } else - reportError(tok, Severity::error, "nullPointer", "Possible null pointer dereference: " + varname, 476U, inconclusive); + reportError(tok, Severity::error, "nullPointer", "Possible null pointer dereference: " + varname, CWE476, inconclusive); } void CheckNullPointer::nullPointerError(const Token *tok, const std::string &varname, const Token* nullCheck, bool inconclusive) @@ -484,5 +486,5 @@ void CheckNullPointer::nullPointerError(const Token *tok, const std::string &var callstack.push_back(tok); callstack.push_back(nullCheck); const std::string errmsg(ValueFlow::eitherTheConditionIsRedundant(nullCheck) + " or there is possible null pointer dereference: " + varname + "."); - reportError(callstack, Severity::warning, "nullPointerRedundantCheck", errmsg, 0U, inconclusive); + reportError(callstack, Severity::warning, "nullPointerRedundantCheck", errmsg, CWE(0U), inconclusive); } diff --git a/lib/checkother.cpp b/lib/checkother.cpp index aa71d89a8..3be57f901 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -33,7 +33,10 @@ namespace { CheckOther instance; } - +static const struct CWE CWE369(369U); +static const struct CWE CWE563(563U); +static const struct CWE CWE686(686U); +static const struct CWE CWE758(758U); //---------------------------------------------------------------------------------- // The return value of fgetc(), getc(), ungetc(), getchar() etc. is an integer value. @@ -230,7 +233,7 @@ void CheckOther::checkSuspiciousSemicolon() void CheckOther::SuspiciousSemicolonError(const Token* tok) { reportError(tok, Severity::warning, "suspiciousSemicolon", - "Suspicious use of ; at the end of '" + (tok ? tok->str() : std::string()) + "' statement.", 0U, true); + "Suspicious use of ; at the end of '" + (tok ? tok->str() : std::string()) + "' statement.", CWE(0U), true); } @@ -379,7 +382,7 @@ void CheckOther::invalidPointerCastError(const Token* tok, const std::string& fr if (!inconclusive) reportError(tok, Severity::portability, "invalidPointerCast", "Casting from " + from + "* to integer* is not portable due to different binary data representations on different platforms."); else - reportError(tok, Severity::portability, "invalidPointerCast", "Casting from " + from + "* to char* is not portable due to different binary data representations on different platforms.", 0U, true); + reportError(tok, Severity::portability, "invalidPointerCast", "Casting from " + from + "* to char* is not portable due to different binary data representations on different platforms.", CWE(0U), true); } else reportError(tok, Severity::portability, "invalidPointerCast", "Casting between " + from + "* and " + to + "* which have an incompatible binary data representation."); } @@ -423,7 +426,7 @@ void CheckOther::checkPipeParameterSizeError(const Token *tok, const std::string reportError(tok, Severity::error, "wrongPipeParameterSize", "Buffer '" + strVarName + "' must have size of 2 integers if used as parameter of pipe().\n" "The pipe()/pipe2() system command takes an argument, which is an array of exactly two integers.\n" - "The variable '" + strVarName + "' is an array of size " + strDim + ", which does not match.", 686U, false); + "The variable '" + strVarName + "' is an array of size " + strDim + ", which does not match.", CWE686, false); } //--------------------------------------------------------------------------- @@ -653,7 +656,7 @@ void CheckOther::redundantAssignmentError(const Token *tok1, const Token* tok2, if (inconclusive) reportError(callstack, Severity::style, "redundantAssignment", "Variable '" + var + "' is reassigned a value before the old one has been used if variable is no semaphore variable.\n" - "Variable '" + var + "' is reassigned a value before the old one has been used. Make sure that this variable is not used like a semaphore in a threading environment before simplifying this code.", 0U, true); + "Variable '" + var + "' is reassigned a value before the old one has been used. Make sure that this variable is not used like a semaphore in a threading environment before simplifying this code.", CWE(0U), true); else reportError(callstack, Severity::style, "redundantAssignment", "Variable '" + var + "' is reassigned a value before the old one has been used."); @@ -918,7 +921,7 @@ void CheckOther::suspiciousCaseInSwitchError(const Token* tok, const std::string { reportError(tok, Severity::warning, "suspiciousCase", "Found suspicious case label in switch(). Operator '" + operatorString + "' probably doesn't work as intended.\n" - "Using an operator like '" + operatorString + "' in a case label is suspicious. Did you intend to use a bitwise operator, multiple case labels or if/else instead?", 0U, true); + "Using an operator like '" + operatorString + "' in a case label is suspicious. Did you intend to use a bitwise operator, multiple case labels or if/else instead?", CWE(0U), true); } //--------------------------------------------------------------------------- @@ -970,7 +973,7 @@ void CheckOther::checkSuspiciousEqualityComparison() void CheckOther::suspiciousEqualityComparisonError(const Token* tok) { reportError(tok, Severity::warning, "suspiciousEqualityComparison", - "Found suspicious equality comparison. Did you intend to assign a value instead?", 0U, true); + "Found suspicious equality comparison. Did you intend to assign a value instead?", CWE(0U), true); } @@ -1082,13 +1085,13 @@ void CheckOther::duplicateBreakError(const Token *tok, bool inconclusive) reportError(tok, Severity::style, "duplicateBreak", "Consecutive return, break, continue, goto or throw statements are unnecessary.\n" "Consecutive return, break, continue, goto or throw statements are unnecessary. " - "The second statement can never be executed, and so should be removed.", 0U, inconclusive); + "The second statement can never be executed, and so should be removed.", CWE(0U), inconclusive); } void CheckOther::unreachableCodeError(const Token *tok, bool inconclusive) { reportError(tok, Severity::style, "unreachableCode", - "Statements following return, break, continue, goto or throw will never be executed.", 0U, inconclusive); + "Statements following return, break, continue, goto or throw will never be executed.", CWE(0U), inconclusive); } //--------------------------------------------------------------------------- @@ -1634,7 +1637,7 @@ void CheckOther::checkZeroDivision() void CheckOther::zerodivError(const Token *tok, bool inconclusive) { - reportError(tok, Severity::error, "zerodiv", "Division by zero.", 369U, inconclusive); + reportError(tok, Severity::error, "zerodiv", "Division by zero.", CWE369, inconclusive); } void CheckOther::zerodivcondError(const Token *tokcond, const Token *tokdiv, bool inconclusive) @@ -1645,7 +1648,7 @@ void CheckOther::zerodivcondError(const Token *tokcond, const Token *tokdiv, boo callstack.push_back(tokdiv); } const std::string linenr(MathLib::toString(tokdiv ? tokdiv->linenr() : 0)); - reportError(callstack, Severity::warning, "zerodivcond", ValueFlow::eitherTheConditionIsRedundant(tokcond) + " or there is division by zero at line " + linenr + ".", 0U, inconclusive); + reportError(callstack, Severity::warning, "zerodivcond", ValueFlow::eitherTheConditionIsRedundant(tokcond) + " or there is division by zero at line " + linenr + ".", CWE(0U), inconclusive); } //--------------------------------------------------------------------------- @@ -1705,7 +1708,7 @@ void CheckOther::checkMisusedScopedObject() void CheckOther::misusedScopeObjectError(const Token *tok, const std::string& varname) { reportError(tok, Severity::style, - "unusedScopedObject", "Instance of '" + varname + "' object is destroyed immediately.", 563U, false); + "unusedScopedObject", "Instance of '" + varname + "' object is destroyed immediately.", CWE563, false); } //----------------------------------------------------------------------------- @@ -1770,7 +1773,7 @@ void CheckOther::duplicateBranchError(const Token *tok1, const Token *tok2) reportError(toks, Severity::style, "duplicateBranch", "Found duplicate branches for 'if' and 'else'.\n" "Finding the same code in an 'if' and related 'else' branch is suspicious and " "might indicate a cut and paste or logic error. Please examine this code " - "carefully to determine if it is correct.", 0U, true); + "carefully to determine if it is correct.", CWE(0U), true); } @@ -1848,7 +1851,7 @@ void CheckOther::checkInvalidFree() void CheckOther::invalidFreeError(const Token *tok, bool inconclusive) { - reportError(tok, Severity::error, "invalidFree", "Invalid memory address freed.", 0U, inconclusive); + reportError(tok, Severity::error, "invalidFree", "Invalid memory address freed.", CWE(0U), inconclusive); } @@ -2093,7 +2096,7 @@ void CheckOther::unsignedLessThanZeroError(const Token *tok, const std::string & "Checking if unsigned variable '" + varname + "' is less than zero. An unsigned " "variable will never be negative so it is either pointless or an error to check if it is. " "It's not known if the used constant is a template parameter or not and therefore " - "this message might be a false warning.", 0U, true); + "this message might be a false warning.", CWE(0U), true); } else { reportError(tok, Severity::style, "unsignedLessThanZero", "Checking if unsigned variable '" + varname + "' is less than zero.\n" @@ -2105,7 +2108,7 @@ void CheckOther::unsignedLessThanZeroError(const Token *tok, const std::string & void CheckOther::pointerLessThanZeroError(const Token *tok, bool inconclusive) { reportError(tok, Severity::style, "pointerLessThanZero", - "A pointer can not be negative so it is either pointless or an error to check if it is.", 0U, inconclusive); + "A pointer can not be negative so it is either pointless or an error to check if it is.", CWE(0U), inconclusive); } void CheckOther::unsignedPositiveError(const Token *tok, const std::string &varname, bool inconclusive) @@ -2115,7 +2118,7 @@ void CheckOther::unsignedPositiveError(const Token *tok, const std::string &varn "Unsigned variable '" + varname + "' can't be negative so it is unnecessary to test it.\n" "The unsigned variable '" + varname + "' can't be negative so it is unnecessary to test it. " "It's not known if the used constant is a " - "template parameter or not and therefore this message might be a false warning", 0U, true); + "template parameter or not and therefore this message might be a false warning", CWE(0U), true); } else { reportError(tok, Severity::style, "unsignedPositive", "Unsigned variable '" + varname + "' can't be negative so it is unnecessary to test it."); @@ -2125,7 +2128,7 @@ void CheckOther::unsignedPositiveError(const Token *tok, const std::string &varn void CheckOther::pointerPositiveError(const Token *tok, bool inconclusive) { reportError(tok, Severity::style, "pointerPositive", - "A pointer can not be negative so it is either pointless or an error to check if it is not.", 0U, inconclusive); + "A pointer can not be negative so it is either pointless or an error to check if it is not.", CWE(0U), inconclusive); } /* check if a constructor in given class scope takes a reference */ @@ -2192,7 +2195,7 @@ void CheckOther::redundantCopyError(const Token *tok,const std::string& varname) "Use const reference for '" + varname + "' to avoid unnecessary data copying.\n" "The const variable '"+varname+"' is assigned a copy of the data. You can avoid " "the unnecessary data copying by converting '" + varname + "' to const reference.", - 0U, + CWE(0U), true); // since #5618 that check became inconlusive } @@ -2251,9 +2254,9 @@ void CheckOther::checkNegativeBitwiseShift() void CheckOther::negativeBitwiseShiftError(const Token *tok, int op) { if (op == 1) // LHS - reportError(tok, Severity::error, "shiftNegative", "Shifting a negative value is undefined behaviour", 758U, false); + reportError(tok, Severity::error, "shiftNegative", "Shifting a negative value is undefined behaviour", CWE758, false); else // RHS - reportError(tok, Severity::error, "shiftNegative", "Shifting by a negative value is undefined behaviour", 758U, false); + reportError(tok, Severity::error, "shiftNegative", "Shifting by a negative value is undefined behaviour", CWE758, false); } //--------------------------------------------------------------------------- @@ -2299,11 +2302,11 @@ void CheckOther::incompleteArrayFillError(const Token* tok, const std::string& b if (boolean) reportError(tok, Severity::portability, "incompleteArrayFill", "Array '" + buffer + "' might be filled incompletely. Did you forget to multiply the size given to '" + function + "()' with 'sizeof(*" + buffer + ")'?\n" - "The array '" + buffer + "' is filled incompletely. The function '" + function + "()' needs the size given in bytes, but the type 'bool' is larger than 1 on some platforms. Did you forget to multiply the size with 'sizeof(*" + buffer + ")'?", 0U, true); + "The array '" + buffer + "' is filled incompletely. The function '" + function + "()' needs the size given in bytes, but the type 'bool' is larger than 1 on some platforms. Did you forget to multiply the size with 'sizeof(*" + buffer + ")'?", CWE(0U), true); else reportError(tok, Severity::warning, "incompleteArrayFill", "Array '" + buffer + "' is filled incompletely. Did you forget to multiply the size given to '" + function + "()' with 'sizeof(*" + buffer + ")'?\n" - "The array '" + buffer + "' is filled incompletely. The function '" + function + "()' needs the size given in bytes, but an element of the given array is larger than one byte. Did you forget to multiply the size with 'sizeof(*" + buffer + ")'?", 0U, true); + "The array '" + buffer + "' is filled incompletely. The function '" + function + "()' needs the size given in bytes, but an element of the given array is larger than one byte. Did you forget to multiply the size with 'sizeof(*" + buffer + ")'?", CWE(0U), true); } //--------------------------------------------------------------------------- @@ -2429,7 +2432,7 @@ void CheckOther::checkRedundantPointerOp() void CheckOther::redundantPointerOpError(const Token* tok, const std::string &varname, bool inconclusive) { reportError(tok, Severity::style, "redundantPointerOp", - "Redundant pointer operation on " + varname + " - it's already a pointer.", 0U, inconclusive); + "Redundant pointer operation on " + varname + " - it's already a pointer.", CWE(0U), inconclusive); } void CheckOther::checkInterlockedDecrement() diff --git a/lib/checksizeof.cpp b/lib/checksizeof.cpp index 148bed843..0ee27b018 100644 --- a/lib/checksizeof.cpp +++ b/lib/checksizeof.cpp @@ -287,7 +287,7 @@ void CheckSizeof::sizeofCalculation() void CheckSizeof::sizeofCalculationError(const Token *tok, bool inconclusive) { reportError(tok, Severity::warning, - "sizeofCalculation", "Found calculation inside sizeof().", 0U, inconclusive); + "sizeofCalculation", "Found calculation inside sizeof().", CWE(0U), inconclusive); } //----------------------------------------------------------------------------- @@ -315,7 +315,7 @@ void CheckSizeof::suspiciousSizeofCalculation() void CheckSizeof::multiplySizeofError(const Token *tok) { reportError(tok, Severity::warning, - "multiplySizeof", "Multiplying sizeof() with sizeof() indicates a logic error.", 0U, true); + "multiplySizeof", "Multiplying sizeof() with sizeof() indicates a logic error.", CWE(0U), true); } void CheckSizeof::divideSizeofError(const Token *tok) @@ -323,7 +323,7 @@ void CheckSizeof::divideSizeofError(const Token *tok) reportError(tok, Severity::warning, "divideSizeof", "Division of result of sizeof() on pointer type.\n" "Division of result of sizeof() on pointer type. sizeof() returns the size of the pointer, " - "not the size of the memory area it points to.", 0U, true); + "not the size of the memory area it points to.", CWE(0U), true); } void CheckSizeof::sizeofVoid() diff --git a/lib/checkstl.cpp b/lib/checkstl.cpp index d56fa0749..3fc81269e 100644 --- a/lib/checkstl.cpp +++ b/lib/checkstl.cpp @@ -27,16 +27,20 @@ namespace { CheckStl instance; } +// CWE ids used: +static const struct CWE CWE664(664U); +static const struct CWE CWE788(788U); + // Error message for bad iterator usage.. void CheckStl::invalidIteratorError(const Token *tok, const std::string &iteratorName) { - reportError(tok, Severity::error, "invalidIterator1", "Invalid iterator: " + iteratorName, 664U, false); + reportError(tok, Severity::error, "invalidIterator1", "Invalid iterator: " + iteratorName, CWE664, false); } void CheckStl::iteratorsError(const Token *tok, const std::string &container1, const std::string &container2) { - reportError(tok, Severity::error, "iterators", "Same iterator is used with different containers '" + container1 + "' and '" + container2 + "'.", 664U, false); + reportError(tok, Severity::error, "iterators", "Same iterator is used with different containers '" + container1 + "' and '" + container2 + "'.", CWE664, false); } // Error message used when dereferencing an iterator that has been erased.. @@ -49,12 +53,12 @@ void CheckStl::dereferenceErasedError(const Token *erased, const Token* deref, c reportError(callstack, Severity::error, "eraseDereference", "Iterator '" + itername + "' used after element has been erased.\n" "The iterator '" + itername + "' is invalid after the element it pointed to has been erased. " - "Dereferencing or comparing it with another iterator is invalid operation.", 664U, false); + "Dereferencing or comparing it with another iterator is invalid operation.", CWE664, false); } else { reportError(deref, Severity::error, "eraseDereference", "Invalid iterator '" + itername + "' used.\n" "The iterator '" + itername + "' is invalid before being assigned. " - "Dereferencing or comparing it with another iterator is invalid operation.", 664U, false); + "Dereferencing or comparing it with another iterator is invalid operation.", CWE664, false); } } @@ -235,7 +239,7 @@ void CheckStl::iterators() // Error message for bad iterator usage.. void CheckStl::mismatchingContainersError(const Token *tok) { - reportError(tok, Severity::error, "mismatchingContainers", "Iterators of different containers are used together.", 664U, false); + reportError(tok, Severity::error, "mismatchingContainers", "Iterators of different containers are used together.", CWE664, false); } namespace { @@ -376,9 +380,9 @@ void CheckStl::stlOutOfBounds() void CheckStl::stlOutOfBoundsError(const Token *tok, const std::string &num, const std::string &var, bool at) { if (at) - reportError(tok, Severity::error, "stlOutOfBounds", "When " + num + "==" + var + ".size(), " + var + ".at(" + num + ") is out of bounds.", 788U, false); + reportError(tok, Severity::error, "stlOutOfBounds", "When " + num + "==" + var + ".size(), " + var + ".at(" + num + ") is out of bounds.", CWE788, false); else - reportError(tok, Severity::error, "stlOutOfBounds", "When " + num + "==" + var + ".size(), " + var + "[" + num + "] is out of bounds.", 788U, false); + reportError(tok, Severity::error, "stlOutOfBounds", "When " + num + "==" + var + ".size(), " + var + "[" + num + "] is out of bounds.", CWE788, false); } void CheckStl::erase() @@ -581,14 +585,14 @@ void CheckStl::pushback() // Error message for bad iterator usage.. void CheckStl::invalidIteratorError(const Token *tok, const std::string &func, const std::string &iterator_name) { - reportError(tok, Severity::error, "invalidIterator2", "After " + func + "(), the iterator '" + iterator_name + "' may be invalid.", 664U, false); + reportError(tok, Severity::error, "invalidIterator2", "After " + func + "(), the iterator '" + iterator_name + "' may be invalid.", CWE664, false); } // Error message for bad iterator usage.. void CheckStl::invalidPointerError(const Token *tok, const std::string &func, const std::string &pointer_name) { - reportError(tok, Severity::error, "invalidPointer", "Invalid pointer '" + pointer_name + "' after " + func + "().", 664U, false); + reportError(tok, Severity::error, "invalidPointer", "Invalid pointer '" + pointer_name + "' after " + func + "().", CWE664, false); } @@ -1497,5 +1501,5 @@ void CheckStl::readingEmptyStlContainer() void CheckStl::readingEmptyStlContainerError(const Token *tok) { - reportError(tok, Severity::style, "reademptycontainer", "Reading from empty STL container '" + (tok ? tok->str() : std::string("var")) + "'", 0U, true); + reportError(tok, Severity::style, "reademptycontainer", "Reading from empty STL container '" + (tok ? tok->str() : std::string("var")) + "'", CWE(0U), true); } diff --git a/lib/checktype.cpp b/lib/checktype.cpp index 928259997..dd457f8ae 100644 --- a/lib/checktype.cpp +++ b/lib/checktype.cpp @@ -95,7 +95,7 @@ void CheckType::tooBigBitwiseShiftError(const Token *tok, int lhsbits, const Val errmsg << "Shifting " << lhsbits << "-bit value by " << rhsbits.intvalue << " bits is undefined behaviour"; if (rhsbits.condition) errmsg << ". See condition at line " << rhsbits.condition->linenr() << "."; - reportError(callstack, rhsbits.condition ? Severity::warning : Severity::error, "shiftTooManyBits", errmsg.str(), 0U, rhsbits.inconclusive); + reportError(callstack, rhsbits.condition ? Severity::warning : Severity::error, "shiftTooManyBits", errmsg.str(), CWE(0U), rhsbits.inconclusive); } //--------------------------------------------------------------------------- @@ -149,7 +149,7 @@ void CheckType::integerOverflowError(const Token *tok, const ValueFlow::Value &v value.condition ? Severity::warning : Severity::error, "integerOverflow", msg, - 0U, + CWE(0U), value.inconclusive); }