CWE: refactoring. use constants instead of magic numbers.
This commit is contained in:
parent
cb6c9e1a71
commit
5e10e680da
15
lib/check.h
15
lib/check.h
|
@ -33,6 +33,11 @@
|
||||||
/// @addtogroup Core
|
/// @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.
|
* @brief Interface class that cppcheck uses to communicate with the checks.
|
||||||
* All checking classes must inherit from this class
|
* All checking classes must inherit from this class
|
||||||
|
@ -111,12 +116,12 @@ protected:
|
||||||
/** report an error */
|
/** report an error */
|
||||||
template<typename T, typename U>
|
template<typename T, typename U>
|
||||||
void reportError(const Token *tok, const Severity::SeverityType severity, const T id, const U msg) {
|
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 */
|
/** report an error */
|
||||||
template<typename T, typename U>
|
template<typename T, typename U>
|
||||||
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<const Token *> callstack(1, tok);
|
std::list<const Token *> callstack(1, tok);
|
||||||
reportError(callstack, severity, id, msg, cwe, inconclusive);
|
reportError(callstack, severity, id, msg, cwe, inconclusive);
|
||||||
}
|
}
|
||||||
|
@ -124,14 +129,14 @@ protected:
|
||||||
/** report an error */
|
/** report an error */
|
||||||
template<typename T, typename U>
|
template<typename T, typename U>
|
||||||
void reportError(const std::list<const Token *> &callstack, Severity::SeverityType severity, const T id, const U msg) {
|
void reportError(const std::list<const Token *> &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 */
|
/** report an error */
|
||||||
template<typename T, typename U>
|
template<typename T, typename U>
|
||||||
void reportError(const std::list<const Token *> &callstack, Severity::SeverityType severity, const T id, const U msg, unsigned int cwe, bool inconclusive) {
|
void reportError(const std::list<const Token *> &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);
|
ErrorLogger::ErrorMessage errmsg(callstack, _tokenizer?&_tokenizer->list:0, severity, id, msg, inconclusive);
|
||||||
errmsg._cwe = cwe;
|
errmsg._cwe = cwe.id;
|
||||||
if (_errorLogger)
|
if (_errorLogger)
|
||||||
_errorLogger->reportErr(errmsg);
|
_errorLogger->reportErr(errmsg);
|
||||||
else
|
else
|
||||||
|
|
|
@ -33,6 +33,8 @@ namespace {
|
||||||
static CheckAutoVariables instance;
|
static CheckAutoVariables instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const CWE CWE562(562U);
|
||||||
|
static const CWE CWE590(590U);
|
||||||
|
|
||||||
bool CheckAutoVariables::isPtrArg(const Token *tok)
|
bool CheckAutoVariables::isPtrArg(const Token *tok)
|
||||||
{
|
{
|
||||||
|
@ -287,12 +289,12 @@ void CheckAutoVariables::returnPointerToLocalArray()
|
||||||
|
|
||||||
void CheckAutoVariables::errorReturnAddressToAutoVariable(const Token *tok)
|
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)
|
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)
|
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 "
|
"Dangerous assignment - the function parameter is assigned the address of a local "
|
||||||
"auto-variable. Local auto-variables are reserved from the stack which "
|
"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 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 {
|
} else {
|
||||||
reportError(tok, Severity::error, "autoVariables",
|
reportError(tok, Severity::error, "autoVariables",
|
||||||
"Address of local auto-variable assigned to a function parameter.\n"
|
"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 "
|
"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 "
|
"the function ends. The address is invalid after the function ends and it "
|
||||||
"might 'leak' from the function through the parameter.",
|
"might 'leak' from the function through the parameter.",
|
||||||
562U,
|
CWE562,
|
||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -322,7 +324,7 @@ void CheckAutoVariables::errorReturnAddressOfFunctionParameter(const Token *tok,
|
||||||
"Address of function parameter '" + varname + "' returned.\n"
|
"Address of function parameter '" + varname + "' returned.\n"
|
||||||
"Address of the function parameter '" + varname + "' becomes invalid after the function exits because "
|
"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 "
|
"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)
|
void CheckAutoVariables::errorUselessAssignmentArg(const Token *tok)
|
||||||
|
@ -492,12 +494,12 @@ void CheckAutoVariables::returnReference()
|
||||||
|
|
||||||
void CheckAutoVariables::errorReturnReference(const Token *tok)
|
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)
|
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)
|
void CheckAutoVariables::errorInvalidDeallocation(const Token *tok)
|
||||||
|
@ -507,5 +509,5 @@ void CheckAutoVariables::errorInvalidDeallocation(const Token *tok)
|
||||||
"autovarInvalidDeallocation",
|
"autovarInvalidDeallocation",
|
||||||
"Deallocation of an auto-variable results in undefined behaviour.\n"
|
"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 "
|
"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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,8 @@ namespace {
|
||||||
CheckBool instance;
|
CheckBool instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const CWE CWE571(571);
|
||||||
|
static const CWE CWE587(587);
|
||||||
|
|
||||||
static bool astIsBool(const Token *expr)
|
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",
|
reportError(tok, Severity::style, "bitwiseOnBoolean",
|
||||||
"Boolean variable '" + varname + "' is used in bitwise operation. Did you mean '" + op + "'?",
|
"Boolean variable '" + varname + "' is used in bitwise operation. Did you mean '" + op + "'?",
|
||||||
0U,
|
CWE(0),
|
||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,7 +354,7 @@ void CheckBool::checkAssignBoolToPointer()
|
||||||
void CheckBool::assignBoolToPointerError(const Token *tok)
|
void CheckBool::assignBoolToPointerError(const Token *tok)
|
||||||
{
|
{
|
||||||
reportError(tok, Severity::error, "assignBoolToPointer",
|
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,
|
Severity::error,
|
||||||
"pointerArithBool",
|
"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 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()
|
void CheckBool::checkAssignBoolToFloat()
|
||||||
|
|
|
@ -24,6 +24,8 @@ namespace {
|
||||||
CheckBoost instance;
|
CheckBoost instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const CWE CWE664(664);
|
||||||
|
|
||||||
void CheckBoost::checkBoostForeachModification()
|
void CheckBoost::checkBoostForeachModification()
|
||||||
{
|
{
|
||||||
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
|
@ -55,6 +57,6 @@ void CheckBoost::checkBoostForeachModification()
|
||||||
void CheckBoost::boostForeachError(const Token *tok)
|
void CheckBoost::boostForeachError(const Token *tok)
|
||||||
{
|
{
|
||||||
reportError(tok, Severity::error, "boostForeachError",
|
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
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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<MathLib::bigint> &index)
|
static void makeArrayIndexOutOfBoundsError(std::ostream& oss, const CheckBufferOverrun::ArrayInfo &arrayInfo, const std::vector<MathLib::bigint> &index)
|
||||||
{
|
{
|
||||||
oss << "Array '" << arrayInfo.varname();
|
oss << "Array '" << arrayInfo.varname();
|
||||||
|
@ -61,7 +68,7 @@ void CheckBufferOverrun::arrayIndexOutOfBoundsError(const Token *tok, const Arra
|
||||||
{
|
{
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
makeArrayIndexOutOfBoundsError(oss, arrayInfo, index);
|
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<ValueFlow::Value> &index)
|
void CheckBufferOverrun::arrayIndexOutOfBoundsError(const Token *tok, const ArrayInfo &arrayInfo, const std::vector<ValueFlow::Value> &index)
|
||||||
|
@ -92,7 +99,7 @@ void CheckBufferOverrun::arrayIndexOutOfBoundsError(const Token *tok, const Arra
|
||||||
std::list<const Token *> callstack;
|
std::list<const Token *> callstack;
|
||||||
callstack.push_back(tok);
|
callstack.push_back(tok);
|
||||||
callstack.push_back(condition);
|
callstack.push_back(condition);
|
||||||
reportError(callstack, Severity::warning, "arrayIndexOutOfBoundsCond", errmsg.str(), 0U, false);
|
reportError(callstack, Severity::warning, "arrayIndexOutOfBoundsCond", errmsg.str(), CWE(0U), false);
|
||||||
} else {
|
} else {
|
||||||
std::ostringstream errmsg;
|
std::ostringstream errmsg;
|
||||||
errmsg << "Array '" << arrayInfo.varname();
|
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)
|
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)
|
if (show_size_info)
|
||||||
oss << ": Supplied size " << supplied_size << " is larger than actual size " << actual_size;
|
oss << ": Supplied size " << supplied_size << " is larger than actual size " << actual_size;
|
||||||
oss << '.';
|
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)
|
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"
|
"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 "
|
"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 "
|
"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)
|
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)
|
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 + "(). "
|
"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.";
|
"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)
|
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",
|
reportError(tok, Severity::error, "negativeMemoryAllocationSize",
|
||||||
"Memory allocation size is negative.\n"
|
"Memory allocation size is negative.\n"
|
||||||
"Memory allocation size is negative."
|
"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.";
|
ostr << "Array index " << index.intvalue << " is out of bounds.";
|
||||||
if (index.condition)
|
if (index.condition)
|
||||||
ostr << " Otherwise there is useless condition at line " << index.condition->linenr() << ".";
|
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()
|
CheckBufferOverrun::ArrayInfo::ArrayInfo()
|
||||||
|
|
|
@ -33,31 +33,35 @@
|
||||||
// Register CheckClass..
|
// Register CheckClass..
|
||||||
namespace {
|
namespace {
|
||||||
CheckClass instance;
|
CheckClass instance;
|
||||||
|
}
|
||||||
|
|
||||||
const char * getFunctionTypeName(
|
static const CWE CWE404(404U);
|
||||||
Function::Type type)
|
static const CWE CWE665(665U);
|
||||||
{
|
static const CWE CWE762(762U);
|
||||||
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 "";
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool isPureWithoutBody(Function const & func)
|
static const char * getFunctionTypeName(
|
||||||
{
|
Function::Type type)
|
||||||
return func.isPure() && !func.hasBody();
|
{
|
||||||
|
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)
|
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)
|
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",
|
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.\n"
|
||||||
"Memory for class instance allocated with " + memfunc + "(), but class provides constructors. This is unsafe, "
|
"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)
|
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",
|
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 contains a " + classname + ".\n"
|
||||||
"Memory for class instance allocated with " + memfunc + "(), but class a " + classname + ". This is unsafe, "
|
"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)
|
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 + ".\n"
|
||||||
"Using '" + memfunc + "' on " + type + " that contains a " + classname + " is unsafe, because constructor, destructor "
|
"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 "
|
"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)
|
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)
|
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)
|
void CheckClass::virtualDestructorError(const Token *tok, const std::string &Base, const std::string &Derived, bool inconclusive)
|
||||||
{
|
{
|
||||||
if (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
|
else
|
||||||
reportError(tok, Severity::error, "virtualDestructor", "Class '" + Base + "' which is inherited by class '" + Derived + "' does not have a virtual destructor.\n"
|
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. "
|
"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. "
|
"function. Making this function 'const' should not cause compiler errors. "
|
||||||
"Even though the function can be made const function technically it may not make "
|
"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 "
|
"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
|
else
|
||||||
reportError(toks, Severity::performance, "functionStatic",
|
reportError(toks, Severity::performance, "functionStatic",
|
||||||
"Technically the member function '" + classname + "::" + funcname + "' can be static.\n"
|
"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 "
|
"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 "
|
"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 - "
|
"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 "
|
"Members are initialized in the order they are declared, not in the "
|
||||||
"order they are in the initializer list. Keeping the initializer list "
|
"order they are in the initializer list. Keeping the initializer list "
|
||||||
"in the same order that the members were declared prevents order dependent "
|
"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)
|
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);
|
const char * scopeFunctionTypeName = getFunctionTypeName(scopeFunction.type);
|
||||||
reportError(tokStack, Severity::warning, "pureVirtualCall", "Call of pure virtual function '" + purefuncname + "' in " + scopeFunctionTypeName + ".\n"
|
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 +
|
const std::string message = "The " + std::string(derivedIsStruct ? "struct" : "class") + " '" + derivedname +
|
||||||
"' defines member variable with name '" + variablename + "' also defined in its parent " +
|
"' defines member variable with name '" + variablename + "' also defined in its parent " +
|
||||||
std::string(baseIsStruct ? "struct" : "class") + " '" + basename + "'.";
|
std::string(baseIsStruct ? "struct" : "class") + " '" + basename + "'.";
|
||||||
reportError(toks, Severity::warning, "duplInheritedMember", message, 0U, false);
|
reportError(toks, Severity::warning, "duplInheritedMember", message, CWE(0U), false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,7 +122,7 @@ private:
|
||||||
reportError(locationList, Severity::style, "unhandledExceptionSpecification",
|
reportError(locationList, Severity::style, "unhandledExceptionSpecification",
|
||||||
"Unhandled exception specification when calling function " + str1 + "().\n"
|
"Unhandled exception specification when calling function " + str1 + "().\n"
|
||||||
"Unhandled exception specification when calling function " + str1 + "(). "
|
"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) */
|
/** Generate all possible errors (for --errorlist) */
|
||||||
|
|
|
@ -32,6 +32,8 @@ namespace {
|
||||||
CheckFunctions instance;
|
CheckFunctions instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const CWE CWE628(628U);
|
||||||
|
|
||||||
void CheckFunctions::checkProhibitedFunctions()
|
void CheckFunctions::checkProhibitedFunctions()
|
||||||
{
|
{
|
||||||
const bool checkAlloca = _settings->isEnabled("warning") && ((_settings->standards.c >= Standards::C99 && _tokenizer->isC()) || _settings->standards.cpp >= Standards::CPP11);
|
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 << "'.";
|
errmsg << ". The value is " << tok->str() << " but the valid values are '" << validstr << "'.";
|
||||||
else if (tok->isComparisonOp())
|
else if (tok->isComparisonOp())
|
||||||
errmsg << ". The value is 0 or 1 (comparison result) but the valid values are '" << validstr << "'.";
|
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)
|
void CheckFunctions::invalidFunctionArgBoolError(const Token *tok, const std::string &functionName, int argnr)
|
||||||
{
|
{
|
||||||
std::ostringstream errmsg;
|
std::ostringstream errmsg;
|
||||||
errmsg << "Invalid " << functionName << "() argument nr " << argnr << ". A non-boolean value is required.";
|
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)
|
void CheckFunctions::ignoredReturnValueError(const Token* tok, const std::string& function)
|
||||||
{
|
{
|
||||||
reportError(tok, Severity::warning, "ignoredReturnValue",
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,10 @@ namespace {
|
||||||
CheckIO instance;
|
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;
|
// std::cout << std::cout;
|
||||||
|
@ -335,26 +339,26 @@ void CheckIO::fflushOnInputStreamError(const Token *tok, const std::string &varn
|
||||||
void CheckIO::ioWithoutPositioningError(const Token *tok)
|
void CheckIO::ioWithoutPositioningError(const Token *tok)
|
||||||
{
|
{
|
||||||
reportError(tok, Severity::error,
|
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)
|
void CheckIO::readWriteOnlyFileError(const Token *tok)
|
||||||
{
|
{
|
||||||
|
|
||||||
reportError(tok, Severity::error,
|
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)
|
void CheckIO::writeReadOnlyFileError(const Token *tok)
|
||||||
{
|
{
|
||||||
reportError(tok, Severity::error,
|
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)
|
void CheckIO::useClosedFileError(const Token *tok)
|
||||||
{
|
{
|
||||||
reportError(tok, Severity::error,
|
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)
|
void CheckIO::seekOnAppendedFileError(const Token *tok)
|
||||||
|
@ -1715,7 +1719,7 @@ void CheckIO::wrongPrintfScanfArgumentsError(const Token* tok,
|
||||||
<< (numFunction != 1 ? " are" : " is")
|
<< (numFunction != 1 ? " are" : " is")
|
||||||
<< " given.";
|
<< " 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,
|
void CheckIO::wrongPrintfScanfPosixParameterPositionError(const Token* tok, const std::string& functionName,
|
||||||
|
@ -1998,10 +2002,10 @@ void CheckIO::invalidScanfFormatWidthError(const Token* tok, unsigned int numFor
|
||||||
return;
|
return;
|
||||||
errmsg << "Width " << width << " given in format string (no. " << numFormat << ") is smaller than destination buffer"
|
errmsg << "Width " << width << " given in format string (no. " << numFormat << ") is smaller than destination buffer"
|
||||||
<< " '" << varname << "[" << arrlen << "]'.";
|
<< " '" << varname << "[" << arrlen << "]'.";
|
||||||
reportError(tok, Severity::warning, "invalidScanfFormatWidth_smaller", errmsg.str(), 0U, true);
|
reportError(tok, Severity::warning, "invalidScanfFormatWidth_smaller", errmsg.str(), CWE(0U), true);
|
||||||
} else {
|
} else {
|
||||||
errmsg << "Width " << width << " given in format string (no. " << numFormat << ") is larger than destination buffer '"
|
errmsg << "Width " << width << " given in format string (no. " << numFormat << ") is larger than destination buffer '"
|
||||||
<< varname << "[" << arrlen << "]', use %" << (arrlen - 1) << "s to prevent overflowing it.";
|
<< 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,8 @@ namespace {
|
||||||
CheckLeakAutoVar instance;
|
CheckLeakAutoVar instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const CWE CWE672(672U);
|
||||||
|
static const CWE CWE415(415U);
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
void VarInfo::print()
|
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)
|
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)
|
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)
|
void CheckLeakAutoVar::doubleFreeError(const Token *tok, const std::string &varname, int type)
|
||||||
{
|
{
|
||||||
if (_settings->library.isresource(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
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -36,47 +36,50 @@ namespace {
|
||||||
CheckMemoryLeakInClass instance2;
|
CheckMemoryLeakInClass instance2;
|
||||||
CheckMemoryLeakStructMember instance3;
|
CheckMemoryLeakStructMember instance3;
|
||||||
CheckMemoryLeakNoVar instance4;
|
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 <leak-ignore/> in .cfg files.
|
|
||||||
*/
|
|
||||||
const std::set<std::string> call_func_white_list = make_container < std::set<std::string> > ()
|
|
||||||
<< "_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 <leak-ignore/> in .cfg files.
|
||||||
|
*/
|
||||||
|
static const std::set<std::string> call_func_white_list = make_container < std::set<std::string> > ()
|
||||||
|
<< "_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
|
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)
|
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)
|
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)
|
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";
|
const std::string factoryFunc = ptrType == "shared_ptr" ? "make_shared" : "make_unique";
|
||||||
reportError(tok, Severity::warning, "leakUnsafeArgAlloc",
|
reportError(tok, Severity::warning, "leakUnsafeArgAlloc",
|
||||||
"Unsafe allocation. If " + funcName + "() throws, memory could be leaked. Use " + factoryFunc + "<" + objType + ">() instead.",
|
"Unsafe allocation. If " + funcName + "() throws, memory could be leaked. Use " + factoryFunc + "<" + objType + ">() instead.",
|
||||||
0U,
|
CWE(0U),
|
||||||
true); // Inconclusive because funcName may never throw
|
true); // Inconclusive because funcName may never throw
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,8 @@ namespace {
|
||||||
CheckNullPointer instance;
|
CheckNullPointer instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const CWE CWE476(476U);
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
static bool checkNullpointerFunctionCallPlausibility(const Function* func, unsigned int arg)
|
static bool checkNullpointerFunctionCallPlausibility(const Function* func, unsigned int arg)
|
||||||
|
@ -466,16 +468,16 @@ void CheckNullPointer::nullConstantDereference()
|
||||||
|
|
||||||
void CheckNullPointer::nullPointerError(const Token *tok)
|
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)
|
void CheckNullPointer::nullPointerError(const Token *tok, const std::string &varname, bool inconclusive, bool defaultArg)
|
||||||
{
|
{
|
||||||
if (defaultArg) {
|
if (defaultArg) {
|
||||||
if (_settings->isEnabled("warning"))
|
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
|
} 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)
|
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(tok);
|
||||||
callstack.push_back(nullCheck);
|
callstack.push_back(nullCheck);
|
||||||
const std::string errmsg(ValueFlow::eitherTheConditionIsRedundant(nullCheck) + " or there is possible null pointer dereference: " + varname + ".");
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,10 @@ namespace {
|
||||||
CheckOther instance;
|
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.
|
// 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)
|
void CheckOther::SuspiciousSemicolonError(const Token* tok)
|
||||||
{
|
{
|
||||||
reportError(tok, Severity::warning, "suspiciousSemicolon",
|
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)
|
if (!inconclusive)
|
||||||
reportError(tok, Severity::portability, "invalidPointerCast", "Casting from " + from + "* to integer* is not portable due to different binary data representations on different platforms.");
|
reportError(tok, Severity::portability, "invalidPointerCast", "Casting from " + from + "* to integer* is not portable due to different binary data representations on different platforms.");
|
||||||
else
|
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
|
} else
|
||||||
reportError(tok, Severity::portability, "invalidPointerCast", "Casting between " + from + "* and " + to + "* which have an incompatible binary data representation.");
|
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,
|
reportError(tok, Severity::error,
|
||||||
"wrongPipeParameterSize", "Buffer '" + strVarName + "' must have size of 2 integers if used as parameter of pipe().\n"
|
"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 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)
|
if (inconclusive)
|
||||||
reportError(callstack, Severity::style, "redundantAssignment",
|
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 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
|
else
|
||||||
reportError(callstack, Severity::style, "redundantAssignment",
|
reportError(callstack, Severity::style, "redundantAssignment",
|
||||||
"Variable '" + var + "' is reassigned a value before the old one has been used.");
|
"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",
|
reportError(tok, Severity::warning, "suspiciousCase",
|
||||||
"Found suspicious case label in switch(). Operator '" + operatorString + "' probably doesn't work as intended.\n"
|
"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)
|
void CheckOther::suspiciousEqualityComparisonError(const Token* tok)
|
||||||
{
|
{
|
||||||
reportError(tok, Severity::warning, "suspiciousEqualityComparison",
|
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",
|
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.\n"
|
||||||
"Consecutive return, break, continue, goto or throw statements are unnecessary. "
|
"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)
|
void CheckOther::unreachableCodeError(const Token *tok, bool inconclusive)
|
||||||
{
|
{
|
||||||
reportError(tok, Severity::style, "unreachableCode",
|
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)
|
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)
|
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);
|
callstack.push_back(tokdiv);
|
||||||
}
|
}
|
||||||
const std::string linenr(MathLib::toString(tokdiv ? tokdiv->linenr() : 0));
|
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)
|
void CheckOther::misusedScopeObjectError(const Token *tok, const std::string& varname)
|
||||||
{
|
{
|
||||||
reportError(tok, Severity::style,
|
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"
|
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 "
|
"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 "
|
"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)
|
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 "
|
"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. "
|
"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 "
|
"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 {
|
} else {
|
||||||
reportError(tok, Severity::style, "unsignedLessThanZero",
|
reportError(tok, Severity::style, "unsignedLessThanZero",
|
||||||
"Checking if unsigned variable '" + varname + "' is less than zero.\n"
|
"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)
|
void CheckOther::pointerLessThanZeroError(const Token *tok, bool inconclusive)
|
||||||
{
|
{
|
||||||
reportError(tok, Severity::style, "pointerLessThanZero",
|
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)
|
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"
|
"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. "
|
"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 "
|
"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 {
|
} else {
|
||||||
reportError(tok, Severity::style, "unsignedPositive",
|
reportError(tok, Severity::style, "unsignedPositive",
|
||||||
"Unsigned variable '" + varname + "' can't be negative so it is unnecessary to test it.");
|
"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)
|
void CheckOther::pointerPositiveError(const Token *tok, bool inconclusive)
|
||||||
{
|
{
|
||||||
reportError(tok, Severity::style, "pointerPositive",
|
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 */
|
/* 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"
|
"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 const variable '"+varname+"' is assigned a copy of the data. You can avoid "
|
||||||
"the unnecessary data copying by converting '" + varname + "' to const reference.",
|
"the unnecessary data copying by converting '" + varname + "' to const reference.",
|
||||||
0U,
|
CWE(0U),
|
||||||
true); // since #5618 that check became inconlusive
|
true); // since #5618 that check became inconlusive
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2251,9 +2254,9 @@ void CheckOther::checkNegativeBitwiseShift()
|
||||||
void CheckOther::negativeBitwiseShiftError(const Token *tok, int op)
|
void CheckOther::negativeBitwiseShiftError(const Token *tok, int op)
|
||||||
{
|
{
|
||||||
if (op == 1) // LHS
|
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
|
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)
|
if (boolean)
|
||||||
reportError(tok, Severity::portability, "incompleteArrayFill",
|
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"
|
"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
|
else
|
||||||
reportError(tok, Severity::warning, "incompleteArrayFill",
|
reportError(tok, Severity::warning, "incompleteArrayFill",
|
||||||
"Array '" + buffer + "' is filled incompletely. Did you forget to multiply the size given to '" + function + "()' with 'sizeof(*" + buffer + ")'?\n"
|
"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)
|
void CheckOther::redundantPointerOpError(const Token* tok, const std::string &varname, bool inconclusive)
|
||||||
{
|
{
|
||||||
reportError(tok, Severity::style, "redundantPointerOp",
|
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()
|
void CheckOther::checkInterlockedDecrement()
|
||||||
|
|
|
@ -287,7 +287,7 @@ void CheckSizeof::sizeofCalculation()
|
||||||
void CheckSizeof::sizeofCalculationError(const Token *tok, bool inconclusive)
|
void CheckSizeof::sizeofCalculationError(const Token *tok, bool inconclusive)
|
||||||
{
|
{
|
||||||
reportError(tok, Severity::warning,
|
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)
|
void CheckSizeof::multiplySizeofError(const Token *tok)
|
||||||
{
|
{
|
||||||
reportError(tok, Severity::warning,
|
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)
|
void CheckSizeof::divideSizeofError(const Token *tok)
|
||||||
|
@ -323,7 +323,7 @@ void CheckSizeof::divideSizeofError(const Token *tok)
|
||||||
reportError(tok, Severity::warning,
|
reportError(tok, Severity::warning,
|
||||||
"divideSizeof", "Division of result of sizeof() on pointer type.\n"
|
"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, "
|
"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()
|
void CheckSizeof::sizeofVoid()
|
||||||
|
|
|
@ -27,16 +27,20 @@ namespace {
|
||||||
CheckStl instance;
|
CheckStl instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CWE ids used:
|
||||||
|
static const struct CWE CWE664(664U);
|
||||||
|
static const struct CWE CWE788(788U);
|
||||||
|
|
||||||
|
|
||||||
// Error message for bad iterator usage..
|
// Error message for bad iterator usage..
|
||||||
void CheckStl::invalidIteratorError(const Token *tok, const std::string &iteratorName)
|
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)
|
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..
|
// 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",
|
reportError(callstack, Severity::error, "eraseDereference",
|
||||||
"Iterator '" + itername + "' used after element has been erased.\n"
|
"Iterator '" + itername + "' used after element has been erased.\n"
|
||||||
"The iterator '" + itername + "' is invalid after the element it pointed to has been erased. "
|
"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 {
|
} else {
|
||||||
reportError(deref, Severity::error, "eraseDereference",
|
reportError(deref, Severity::error, "eraseDereference",
|
||||||
"Invalid iterator '" + itername + "' used.\n"
|
"Invalid iterator '" + itername + "' used.\n"
|
||||||
"The iterator '" + itername + "' is invalid before being assigned. "
|
"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..
|
// Error message for bad iterator usage..
|
||||||
void CheckStl::mismatchingContainersError(const Token *tok)
|
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 {
|
namespace {
|
||||||
|
@ -376,9 +380,9 @@ void CheckStl::stlOutOfBounds()
|
||||||
void CheckStl::stlOutOfBoundsError(const Token *tok, const std::string &num, const std::string &var, bool at)
|
void CheckStl::stlOutOfBoundsError(const Token *tok, const std::string &num, const std::string &var, bool at)
|
||||||
{
|
{
|
||||||
if (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
|
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()
|
void CheckStl::erase()
|
||||||
|
@ -581,14 +585,14 @@ void CheckStl::pushback()
|
||||||
// Error message for bad iterator usage..
|
// Error message for bad iterator usage..
|
||||||
void CheckStl::invalidIteratorError(const Token *tok, const std::string &func, const std::string &iterator_name)
|
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..
|
// Error message for bad iterator usage..
|
||||||
void CheckStl::invalidPointerError(const Token *tok, const std::string &func, const std::string &pointer_name)
|
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)
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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";
|
errmsg << "Shifting " << lhsbits << "-bit value by " << rhsbits.intvalue << " bits is undefined behaviour";
|
||||||
if (rhsbits.condition)
|
if (rhsbits.condition)
|
||||||
errmsg << ". See condition at line " << rhsbits.condition->linenr() << ".";
|
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,
|
value.condition ? Severity::warning : Severity::error,
|
||||||
"integerOverflow",
|
"integerOverflow",
|
||||||
msg,
|
msg,
|
||||||
0U,
|
CWE(0U),
|
||||||
value.inconclusive);
|
value.inconclusive);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue