From 88f59ad7e80f5769f72e42e97bb652941618640c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sat, 25 Apr 2015 17:48:11 +0200 Subject: [PATCH] Partial fix for #6656 (Allow that CWE is mapped for error message) --- lib/check.h | 21 ++++++++++++++++---- lib/checkautovariables.cpp | 4 +++- lib/checkbool.cpp | 4 +++- lib/checkbufferoverrun.cpp | 12 ++++++------ lib/checkclass.cpp | 20 +++++++++---------- lib/checkexceptionsafety.h | 2 +- lib/checkio.cpp | 4 ++-- lib/checkmemoryleak.cpp | 25 ++++++++++++------------ lib/checkmemoryleak.h | 6 ++++-- lib/checknullpointer.cpp | 6 +++--- lib/checkother.cpp | 39 +++++++++++++++++++------------------- lib/checksizeof.cpp | 6 +++--- lib/checkstl.cpp | 2 +- lib/checktype.cpp | 3 ++- lib/errorlogger.cpp | 17 +++++++++++------ lib/errorlogger.h | 1 + test/testerrorlogger.cpp | 12 +++++++----- 17 files changed, 107 insertions(+), 77 deletions(-) diff --git a/lib/check.h b/lib/check.h index 9aa4418ce..2189e4264 100644 --- a/lib/check.h +++ b/lib/check.h @@ -109,15 +109,28 @@ protected: /** report an error */ template - void reportError(const Token *tok, const Severity::SeverityType severity, const T id, const U msg, bool inconclusive = false) { - std::list callstack(1, tok); - reportError(callstack, severity, id, msg, inconclusive); + void reportError(const Token *tok, const Severity::SeverityType severity, const T id, const U msg) { + reportError(tok, severity, id, msg, 0U, false); } /** report an error */ template - void reportError(const std::list &callstack, Severity::SeverityType severity, const T id, const U msg, bool inconclusive = false) { + void reportError(const Token *tok, const Severity::SeverityType severity, const T id, const U msg, unsigned int cwe, bool inconclusive) { + std::list callstack(1, tok); + reportError(callstack, severity, id, msg, cwe, inconclusive); + } + + /** 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); + } + + /** report an error */ + template + void reportError(const std::list &callstack, Severity::SeverityType severity, const T id, const U msg, unsigned int cwe, bool inconclusive) { ErrorLogger::ErrorMessage errmsg(callstack, _tokenizer?&_tokenizer->list:0, severity, id, msg, inconclusive); + errmsg._cwe = cwe; if (_errorLogger) _errorLogger->reportErr(errmsg); else diff --git a/lib/checkautovariables.cpp b/lib/checkautovariables.cpp index 65e949b55..55f05e7b1 100644 --- a/lib/checkautovariables.cpp +++ b/lib/checkautovariables.cpp @@ -268,7 +268,9 @@ void CheckAutoVariables::errorAutoVariableAssignment(const Token *tok, bool inco "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. The address is invalid after the function ends and it " - "might 'leak' from the function through the parameter.", true); + "might 'leak' from the function through the parameter.", + 0U, + true); } } diff --git a/lib/checkbool.cpp b/lib/checkbool.cpp index a03943599..14b44d87f 100644 --- a/lib/checkbool.cpp +++ b/lib/checkbool.cpp @@ -105,7 +105,9 @@ void CheckBool::checkBitwiseOnBoolean() void CheckBool::bitwiseOnBooleanError(const Token *tok, const std::string &varname, const std::string &op) { reportError(tok, Severity::style, "bitwiseOnBoolean", - "Boolean variable '" + varname + "' is used in bitwise operation. Did you mean '" + op + "'?", true); + "Boolean variable '" + varname + "' is used in bitwise operation. Did you mean '" + op + "'?", + 0U, + true); } //--------------------------------------------------------------------------- diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp index fcbfc470a..74b240c51 100644 --- a/lib/checkbufferoverrun.cpp +++ b/lib/checkbufferoverrun.cpp @@ -91,7 +91,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()); + reportError(callstack, Severity::warning, "arrayIndexOutOfBoundsCond", errmsg.str(), 0U, false); } else { reportError(tok, Severity::error, "arrayIndexOutOfBounds", errmsg.str()); } @@ -101,7 +101,7 @@ void CheckBufferOverrun::arrayIndexOutOfBoundsError(const std::list &callstack, const std::string &varnames) { - reportError(callstack, Severity::error, "bufferAccessOutOfBounds", bufferOverrunMessage(varnames)); + reportError(callstack, Severity::error, "bufferAccessOutOfBounds", bufferOverrunMessage(varnames), 0U, false); } void CheckBufferOverrun::possibleBufferOverrunError(const Token *tok, const std::string &src, const std::string &dst, bool cat) @@ -207,7 +207,7 @@ 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.", true); + "assumes buffer is null-terminated.", 0U, true); } void CheckBufferOverrun::cmdLineArgsError(const Token *tok) @@ -221,7 +221,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, true); + reportError(tok, Severity::warning, "bufferNotZeroTerminated", errmsg, 0U, true); } void CheckBufferOverrun::argumentSizeError(const Token *tok, const std::string &functionName, const std::string &varname) @@ -1613,7 +1613,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(), index.inconclusive); + reportError(tok, index.condition ? Severity::warning : Severity::error, "negativeIndex", ostr.str(), 0U, index.inconclusive); } CheckBufferOverrun::ArrayInfo::ArrayInfo() diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 1145d2a1f..951d9d725 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -784,12 +784,12 @@ void CheckClass::noExplicitCopyMoveConstructorError(const Token *tok, const std: 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.", inconclusive); + reportError(tok, Severity::warning, "uninitMemberVar", "Member variable '" + classname + "::" + varname + "' is not initialized in the constructor.", 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='.", inconclusive); + reportError(tok, Severity::warning, "operatorEqVarError", "Member variable '" + classname + "::" + varname + "' is not assigned a value in '" + classname + "::operator='.", 0U, inconclusive); } //--------------------------------------------------------------------------- @@ -1129,7 +1129,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."); + "since no constructor is called and class members remain uninitialized. Consider using 'new' instead.", 0U, false); } void CheckClass::mallocOnClassError(const Token* tok, const std::string &memfunc, const Token* classTok, const std::string &classname) @@ -1140,7 +1140,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."); + "since no constructor is called and class members remain uninitialized. Consider using 'new' instead.", 0U, false); } void CheckClass::memsetError(const Token *tok, const std::string &memfunc, const std::string &classname, const std::string &type) @@ -1604,7 +1604,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.", true); + reportError(tok, Severity::warning, "virtualDestructor", "Class '" + Base + "' which has virtual members does not have a virtual destructor.", 0U, 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. " @@ -1973,7 +1973,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?", true); + "it a function that must not change object internal state?", 0U, true); else reportError(toks, Severity::performance, "functionStatic", "Technically the member function '" + classname + "::" + funcname + "' can be static.\n" @@ -1981,7 +1981,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?", true); + "is it a function that must not access members of class instances?", 0U, true); } //--------------------------------------------------------------------------- @@ -2066,7 +2066,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.", true); + "initialization errors.", 0U, true); } @@ -2215,7 +2215,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."); + "Call of pure virtual function '" + purefuncname + "' in " + scopeFunctionTypeName + ". The call will fail during runtime.", 0U, false); } @@ -2269,5 +2269,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); + reportError(toks, Severity::warning, "duplInheritedMember", message, 0U, false); } diff --git a/lib/checkexceptionsafety.h b/lib/checkexceptionsafety.h index 19c4f391a..a9fa53fef 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.", true); + "Either use a try/catch around the function call, or add a exception specification for " + funcname + "() also.", 0U, true); } /** Generate all possible errors (for --errorlist) */ diff --git a/lib/checkio.cpp b/lib/checkio.cpp index 448d32378..8f11607f3 100644 --- a/lib/checkio.cpp +++ b/lib/checkio.cpp @@ -1971,10 +1971,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(), true); + reportError(tok, Severity::warning, "invalidScanfFormatWidth_smaller", errmsg.str(), 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(), false); + reportError(tok, Severity::error, "invalidScanfFormatWidth", errmsg.str(), 0U, false); } } diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index 2dfa7944e..d1bc095be 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -340,20 +340,20 @@ void CheckMemoryLeak::memoryLeak(const Token *tok, const std::string &varname, A } //--------------------------------------------------------------------------- - -void CheckMemoryLeak::reportErr(const Token *tok, Severity::SeverityType severity, const std::string &id, const std::string &msg) const +void CheckMemoryLeak::reportErr(const Token *tok, Severity::SeverityType severity, const std::string &id, const std::string &msg, unsigned int cwe) const { std::list callstack; if (tok) callstack.push_back(tok); - reportErr(callstack, severity, id, msg); + reportErr(callstack, severity, id, msg, cwe); } -void CheckMemoryLeak::reportErr(const std::list &callstack, Severity::SeverityType severity, const std::string &id, const std::string &msg) const +void CheckMemoryLeak::reportErr(const std::list &callstack, Severity::SeverityType severity, const std::string &id, const std::string &msg, unsigned int cwe) const { - const ErrorLogger::ErrorMessage errmsg(callstack, tokenizer?&tokenizer->list:0, severity, id, msg, false); + ErrorLogger::ErrorMessage errmsg(callstack, tokenizer?&tokenizer->list:0, severity, id, msg, false); + errmsg._cwe = cwe; if (errorLogger) errorLogger->reportErr(errmsg); @@ -363,12 +363,12 @@ void CheckMemoryLeak::reportErr(const std::list &callstack, Sever void CheckMemoryLeak::memleakError(const Token *tok, const std::string &varname) const { - reportErr(tok, Severity::error, "memleak", "Memory leak: " + varname); + reportErr(tok, Severity::error, "memleak", "Memory leak: " + varname, 0U); } void CheckMemoryLeak::memleakUponReallocFailureError(const Token *tok, const std::string &varname) const { - reportErr(tok, Severity::error, "memleakOnRealloc", "Common realloc mistake: \'" + varname + "\' nulled but not freed upon failure"); + reportErr(tok, Severity::error, "memleakOnRealloc", "Common realloc mistake: \'" + varname + "\' nulled but not freed upon failure", 0U); } void CheckMemoryLeak::resourceLeakError(const Token *tok, const std::string &varname) const @@ -376,27 +376,27 @@ void CheckMemoryLeak::resourceLeakError(const Token *tok, const std::string &var std::string errmsg("Resource leak"); if (!varname.empty()) errmsg += ": " + varname; - reportErr(tok, Severity::error, "resourceLeak", errmsg); + reportErr(tok, Severity::error, "resourceLeak", errmsg, 775U); } void CheckMemoryLeak::deallocDeallocError(const Token *tok, const std::string &varname) const { - reportErr(tok, Severity::error, "deallocDealloc", "Deallocating a deallocated pointer: " + varname); + reportErr(tok, Severity::error, "deallocDealloc", "Deallocating a deallocated pointer: " + varname, 0U); } void CheckMemoryLeak::deallocuseError(const Token *tok, const std::string &varname) const { - reportErr(tok, Severity::error, "deallocuse", "Dereferencing '" + varname + "' after it is deallocated / released"); + reportErr(tok, Severity::error, "deallocuse", "Dereferencing '" + varname + "' after it is deallocated / released", 0U); } void CheckMemoryLeak::mismatchSizeError(const Token *tok, const std::string &sz) const { - reportErr(tok, Severity::error, "mismatchSize", "The allocated size " + sz + " is not a multiple of the underlying type's size."); + reportErr(tok, Severity::error, "mismatchSize", "The allocated size " + sz + " is not a multiple of the underlying type's size.", 0U); } void CheckMemoryLeak::mismatchAllocDealloc(const std::list &callstack, const std::string &varname) const { - reportErr(callstack, Severity::error, "mismatchAllocDealloc", "Mismatching allocation and deallocation: " + varname); + reportErr(callstack, Severity::error, "mismatchAllocDealloc", "Mismatching allocation and deallocation: " + varname, 0U); } CheckMemoryLeak::AllocType CheckMemoryLeak::functionReturnType(const Function* func, std::list *callstack) const @@ -2817,5 +2817,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, true); // Inconclusive because funcName may never throw } diff --git a/lib/checkmemoryleak.h b/lib/checkmemoryleak.h index ab7433b16..7df103ec4 100644 --- a/lib/checkmemoryleak.h +++ b/lib/checkmemoryleak.h @@ -73,8 +73,9 @@ private: * @param severity the severity of the bug * @param id type of message * @param msg text + * @param cwe cwe number */ - void reportErr(const Token *location, Severity::SeverityType severity, const std::string &id, const std::string &msg) const; + void reportErr(const Token *location, Severity::SeverityType severity, const std::string &id, const std::string &msg, unsigned int cwe) const; /** * Report error. Similar with the function Check::reportError @@ -82,8 +83,9 @@ private: * @param severity the severity of the bug * @param id type of message * @param msg text + * @param cwe cwe number */ - void reportErr(const std::list &callstack, Severity::SeverityType severity, const std::string &id, const std::string &msg) const; + void reportErr(const std::list &callstack, Severity::SeverityType severity, const std::string &id, const std::string &msg, unsigned int cwe) const; public: CheckMemoryLeak(const Tokenizer *t, ErrorLogger *e, const Settings *s) diff --git a/lib/checknullpointer.cpp b/lib/checknullpointer.cpp index 686b67904..38b01ce25 100644 --- a/lib/checknullpointer.cpp +++ b/lib/checknullpointer.cpp @@ -468,9 +468,9 @@ void CheckNullPointer::nullPointerError(const Token *tok, const std::string &var { if (defaultArg) { if (_settings->isEnabled("warning")) - reportError(tok, Severity::warning, "nullPointer", "Possible null pointer dereference if the default parameter value is used: " + varname, inconclusive); + reportError(tok, Severity::warning, "nullPointer", "Possible null pointer dereference if the default parameter value is used: " + varname, 0U, inconclusive); } else - reportError(tok, Severity::error, "nullPointer", "Possible null pointer dereference: " + varname, inconclusive); + reportError(tok, Severity::error, "nullPointer", "Possible null pointer dereference: " + varname, 0U, inconclusive); } void CheckNullPointer::nullPointerError(const Token *tok, const std::string &varname, const Token* nullCheck, bool inconclusive) @@ -479,5 +479,5 @@ void CheckNullPointer::nullPointerError(const Token *tok, const std::string &var callstack.push_back(tok); callstack.push_back(nullCheck); const std::string errmsg("Possible null pointer dereference: " + varname + " - otherwise it is redundant to check it against null."); - reportError(callstack, Severity::warning, "nullPointer", errmsg, inconclusive); + reportError(callstack, Severity::warning, "nullPointer", errmsg, 0U, inconclusive); } diff --git a/lib/checkother.cpp b/lib/checkother.cpp index b12ad1ff6..cf385c1ab 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -353,7 +353,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.", true); + "Suspicious use of ; at the end of '" + (tok ? tok->str() : std::string()) + "' statement.", 0U, true); } @@ -504,7 +504,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.", true); + reportError(tok, Severity::portability, "invalidPointerCast", "Casting from " + from + "* to char* is not portable due to different binary data representations on different platforms.", 0U, true); } else reportError(tok, Severity::portability, "invalidPointerCast", "Casting between " + from + "* and " + to + "* which have an incompatible binary data representation."); } @@ -758,7 +758,7 @@ void CheckOther::redundantAssignmentError(const Token *tok1, const Token* tok2, if (inconclusive) reportError(callstack, Severity::performance, "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.", 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.", 0U, true); else reportError(callstack, Severity::performance, "redundantAssignment", "Variable '" + var + "' is reassigned a value before the old one has been used."); @@ -999,7 +999,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?", 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?", 0U, true); } //--------------------------------------------------------------------------- @@ -1061,7 +1061,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?", true); + "Found suspicious equality comparison. Did you intend to assign a value instead?", 0U, true); } @@ -1235,13 +1235,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.", inconclusive); + "The second statement can never be executed, and so should be removed.", 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.", inconclusive); + "Statements following return, break, continue, goto or throw will never be executed.", 0U, inconclusive); } //--------------------------------------------------------------------------- @@ -1818,7 +1818,7 @@ void CheckOther::checkZeroDivision() void CheckOther::zerodivError(const Token *tok, bool inconclusive) { - reportError(tok, Severity::error, "zerodiv", "Division by zero.", inconclusive); + reportError(tok, Severity::error, "zerodiv", "Division by zero.", 0U, inconclusive); } void CheckOther::zerodivcondError(const Token *tokcond, const Token *tokdiv, bool inconclusive) @@ -1844,7 +1844,7 @@ void CheckOther::zerodivcondError(const Token *tokcond, const Token *tokdiv, boo condition = tokcond->str() + "!=0"; } const std::string linenr(MathLib::toString(tokdiv ? tokdiv->linenr() : 0)); - reportError(callstack, Severity::warning, "zerodivcond", "Either the condition '"+condition+"' is useless or there is division by zero at line " + linenr + ".", inconclusive); + reportError(callstack, Severity::warning, "zerodivcond", "Either the condition '"+condition+"' is useless or there is division by zero at line " + linenr + ".", 0U, inconclusive); } //--------------------------------------------------------------------------- @@ -2061,7 +2061,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.", true); + "carefully to determine if it is correct.", 0U, true); } @@ -2139,7 +2139,7 @@ void CheckOther::checkInvalidFree() void CheckOther::invalidFreeError(const Token *tok, bool inconclusive) { - reportError(tok, Severity::error, "invalidFree", "Invalid memory address freed.", inconclusive); + reportError(tok, Severity::error, "invalidFree", "Invalid memory address freed.", 0U, inconclusive); } @@ -2394,7 +2394,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.", true); + "this message might be a false warning.", 0U, true); } else { reportError(tok, Severity::style, "unsignedLessThanZero", "Checking if unsigned variable '" + varname + "' is less than zero.\n" @@ -2406,7 +2406,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.", inconclusive); + "A pointer can not be negative so it is either pointless or an error to check if it is.", 0U, inconclusive); } void CheckOther::unsignedPositiveError(const Token *tok, const std::string &varname, bool inconclusive) @@ -2416,7 +2416,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", true); + "template parameter or not and therefore this message might be a false warning", 0U, true); } else { reportError(tok, Severity::style, "unsignedPositive", "Unsigned variable '" + varname + "' can't be negative so it is unnecessary to test it."); @@ -2426,7 +2426,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.", inconclusive); + "A pointer can not be negative so it is either pointless or an error to check if it is not.", 0U, inconclusive); } /* check if a constructor in given class scope takes a reference */ @@ -2493,6 +2493,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, true); // since #5618 that check became inconlusive } @@ -2593,11 +2594,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 + ")'?", 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 + ")'?", 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 + ")'?", 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 + ")'?", 0U, true); } //--------------------------------------------------------------------------- @@ -2717,7 +2718,7 @@ void CheckOther::checkIgnoredReturnValue() void CheckOther::ignoredReturnValueError(const Token* tok, const std::string& function) { reportError(tok, Severity::warning, "ignoredReturnValue", - "Return value of function " + function + "() is not used.", false); + "Return value of function " + function + "() is not used.", 0U, false); } void CheckOther::checkRedundantPointerOp() @@ -2754,7 +2755,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.", inconclusive); + "Redundant pointer operation on " + varname + " - it's already a pointer.", 0U, inconclusive); } void CheckOther::checkLibraryMatchFunctions() diff --git a/lib/checksizeof.cpp b/lib/checksizeof.cpp index 64614ef39..84a268b13 100644 --- a/lib/checksizeof.cpp +++ b/lib/checksizeof.cpp @@ -260,7 +260,7 @@ void CheckSizeof::sizeofCalculation() void CheckSizeof::sizeofCalculationError(const Token *tok, bool inconclusive) { reportError(tok, Severity::warning, - "sizeofCalculation", "Found calculation inside sizeof().", inconclusive); + "sizeofCalculation", "Found calculation inside sizeof().", 0U, inconclusive); } //----------------------------------------------------------------------------- @@ -288,7 +288,7 @@ void CheckSizeof::suspiciousSizeofCalculation() void CheckSizeof::multiplySizeofError(const Token *tok) { reportError(tok, Severity::warning, - "multiplySizeof", "Multiplying sizeof() with sizeof() indicates a logic error.", true); + "multiplySizeof", "Multiplying sizeof() with sizeof() indicates a logic error.", 0U, true); } void CheckSizeof::divideSizeofError(const Token *tok) @@ -296,7 +296,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.", true); + "not the size of the memory area it points to.", 0U, true); } void CheckSizeof::sizeofVoid() diff --git a/lib/checkstl.cpp b/lib/checkstl.cpp index 53a87cd82..5dde8be54 100644 --- a/lib/checkstl.cpp +++ b/lib/checkstl.cpp @@ -1612,5 +1612,5 @@ void CheckStl::readingEmptyStlContainer() void CheckStl::readingEmptyStlContainerError(const Token *tok) { - reportError(tok, Severity::style, "reademptycontainer", "Reading from empty STL container", true); + reportError(tok, Severity::style, "reademptycontainer", "Reading from empty STL container", 0U, true); } diff --git a/lib/checktype.cpp b/lib/checktype.cpp index 2094e4996..9ad5af416 100644 --- a/lib/checktype.cpp +++ b/lib/checktype.cpp @@ -156,7 +156,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(), rhsbits.inconclusive); + reportError(callstack, rhsbits.condition ? Severity::warning : Severity::error, "shiftTooManyBits", errmsg.str(), 0U, rhsbits.inconclusive); } //--------------------------------------------------------------------------- @@ -211,6 +211,7 @@ void CheckType::integerOverflowError(const Token *tok, const ValueFlow::Value &v value.condition ? Severity::warning : Severity::error, "integerOverflow", "Signed integer overflow for expression '"+expr+"'"+cond, + 0U, value.inconclusive); } diff --git a/lib/errorlogger.cpp b/lib/errorlogger.cpp index c7571e643..e216cecfa 100644 --- a/lib/errorlogger.cpp +++ b/lib/errorlogger.cpp @@ -45,7 +45,7 @@ InternalError::InternalError(const Token *tok, const std::string &errorMsg, Type } ErrorLogger::ErrorMessage::ErrorMessage() - : _severity(Severity::none), _inconclusive(false) + : _severity(Severity::none), _cwe(0U), _inconclusive(false) { } @@ -53,6 +53,7 @@ ErrorLogger::ErrorMessage::ErrorMessage(const std::list &callStack _callStack(callStack), // locations for this error message _id(id), // set the message id _severity(severity), // severity for this error message + _cwe(0U), _inconclusive(inconclusive) { // set the summary and verbose messages @@ -60,7 +61,7 @@ ErrorLogger::ErrorMessage::ErrorMessage(const std::list &callStack } ErrorLogger::ErrorMessage::ErrorMessage(const std::list& callstack, const TokenList* list, Severity::SeverityType severity, const std::string& id, const std::string& msg, bool inconclusive) - : _id(id), _severity(severity), _inconclusive(inconclusive) + : _id(id), _severity(severity), _cwe(0U), _inconclusive(inconclusive) { // Format callstack for (std::list::const_iterator it = callstack.begin(); it != callstack.end(); ++it) { @@ -105,6 +106,7 @@ std::string ErrorLogger::ErrorMessage::serialize() const std::ostringstream oss; oss << _id.length() << " " << _id; oss << Severity::toString(_severity).length() << " " << Severity::toString(_severity); + oss << MathLib::toString(_cwe).length() << " " << MathLib::toString(_cwe); if (_inconclusive) { const std::string inconclusive("inconclusive"); oss << inconclusive.length() << " " << inconclusive; @@ -150,17 +152,18 @@ bool ErrorLogger::ErrorMessage::deserialize(const std::string &data) } results.push_back(temp); - if (results.size() == 4) + if (results.size() == 5) break; } - if (results.size() != 4) + if (results.size() != 5) throw InternalError(0, "Internal Error: Deserialization of error message failed"); _id = results[0]; _severity = Severity::fromString(results[1]); - _shortMessage = results[2]; - _verboseMessage = results[3]; + _cwe = MathLib::toULongNumber(results[2]); + _shortMessage = results[3]; + _verboseMessage = results[4]; unsigned int stackSize = 0; if (!(iss >> stackSize)) @@ -271,6 +274,8 @@ std::string ErrorLogger::ErrorMessage::toXML(bool verbose, int version) const printer.PushAttribute("severity", Severity::toString(_severity).c_str()); printer.PushAttribute("msg", _shortMessage.c_str()); printer.PushAttribute("verbose", fixInvalidChars(_verboseMessage).c_str()); + if (_cwe) + printer.PushAttribute("cwe", _cwe); if (_inconclusive) printer.PushAttribute("inconclusive", "true"); diff --git a/lib/errorlogger.h b/lib/errorlogger.h index f75dfc158..9c1feaecb 100644 --- a/lib/errorlogger.h +++ b/lib/errorlogger.h @@ -230,6 +230,7 @@ public: std::string file0; Severity::SeverityType _severity; + unsigned int _cwe; bool _inconclusive; /** set short and verbose messages */ diff --git a/test/testerrorlogger.cpp b/test/testerrorlogger.cpp index c35f7edc1..0782c77f3 100644 --- a/test/testerrorlogger.cpp +++ b/test/testerrorlogger.cpp @@ -249,6 +249,7 @@ private: ErrorMessage msg(locs, Severity::error, "Programming error", "errorId", true); ASSERT_EQUALS("7 errorId" "5 error" + "1 0" "12 inconclusive" "17 Programming error" "17 Programming error" @@ -272,11 +273,12 @@ private: std::list locs; ErrorMessage msg(locs, Severity::error, std::string("Illegal character in \"foo\001bar\""), "errorId", false); - ASSERT_EQUALS(std::string("7 errorId") + - std::string("5 error") + - std::string("33 Illegal character in \"foo\\001bar\"") + - std::string("33 Illegal character in \"foo\\001bar\"") + - std::string("0 "), msg.serialize()); + ASSERT_EQUALS("7 errorId" + "5 error" + "1 0" + "33 Illegal character in \"foo\\001bar\"" + "33 Illegal character in \"foo\\001bar\"" + "0 ", msg.serialize()); ErrorMessage msg2; msg2.deserialize(msg.serialize());