doxygen: added more comments for CheckNullPointer and CheckUninitVar
This commit is contained in:
parent
9b550a3f87
commit
30d3418b11
|
@ -35,7 +35,15 @@ class Tokenizer;
|
||||||
/// @addtogroup Checks
|
/// @addtogroup Checks
|
||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief buffer overruns and array index out of bounds
|
||||||
|
*
|
||||||
|
* Buffer overrun and array index out of bounds are pretty much the same.
|
||||||
|
* But I generally use 'array index' if the code contains []. And the given
|
||||||
|
* index is out of bounds.
|
||||||
|
* I generally use 'buffer overrun' if you for example call a strcpy or
|
||||||
|
* other function and pass a buffer and reads or writes too much data.
|
||||||
|
*/
|
||||||
class CheckBufferOverrun : public Check
|
class CheckBufferOverrun : public Check
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -55,14 +63,21 @@ public:
|
||||||
checkBufferOverrun.bufferOverrun();
|
checkBufferOverrun.bufferOverrun();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Check for buffer overruns */
|
/** @brief %Check for buffer overruns */
|
||||||
void bufferOverrun();
|
void bufferOverrun();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get minimum length of format string result
|
||||||
|
* @param input_string format string
|
||||||
|
* @param parameters given parameters to sprintf
|
||||||
|
* @return minimum length of resulting string
|
||||||
|
*/
|
||||||
static int countSprintfLength(const std::string &input_string, const std::list<const Token*> ¶meters);
|
static int countSprintfLength(const std::string &input_string, const std::list<const Token*> ¶meters);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check code that matches: "sprintf ( %varid% , %str% [,)]" when varid is not 0,
|
* @brief %Check code that matches: "sprintf ( %varid% , %str% [,)]" when varid is not 0,
|
||||||
* and report found errors.
|
* and report found errors.
|
||||||
* @param tok The "sprintf" token.
|
* @param tok The "sprintf" token.
|
||||||
* @param size The size of the buffer where sprintf is writing.
|
* @param size The size of the buffer where sprintf is writing.
|
||||||
|
|
|
@ -43,12 +43,16 @@ public:
|
||||||
: Check(tokenizer, settings, errorLogger)
|
: Check(tokenizer, settings, errorLogger)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
/** @brief Run checks on the normal token list */
|
||||||
void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
|
void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
|
||||||
{
|
{
|
||||||
CheckClass checkClass(tokenizer, settings, errorLogger);
|
CheckClass checkClass(tokenizer, settings, errorLogger);
|
||||||
|
|
||||||
|
// can't be a simplified check .. the 'sizeof' is used.
|
||||||
checkClass.noMemset();
|
checkClass.noMemset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @brief Run checks on the simplified token list */
|
||||||
void runSimplifiedChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
|
void runSimplifiedChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
|
||||||
{
|
{
|
||||||
CheckClass checkClass(tokenizer, settings, errorLogger);
|
CheckClass checkClass(tokenizer, settings, errorLogger);
|
||||||
|
@ -78,7 +82,10 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief %Check that the memsets are valid.
|
* @brief %Check that the memsets are valid.
|
||||||
* The 'memset' function can do dangerous things if used wrong.
|
* The 'memset' function can do dangerous things if used wrong. If it
|
||||||
|
* is used on STL containers for instance it will clear all its data
|
||||||
|
* and then the STL container may leak memory or worse have an invalid state.
|
||||||
|
* It can also overwrite the virtual table.
|
||||||
* Important: The checking doesn't work on simplified tokens list.
|
* Important: The checking doesn't work on simplified tokens list.
|
||||||
*/
|
*/
|
||||||
void noMemset();
|
void noMemset();
|
||||||
|
|
|
@ -27,6 +27,10 @@
|
||||||
/// @addtogroup Checks
|
/// @addtogroup Checks
|
||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Using dangerous functions that are always insecure to use.
|
||||||
|
*/
|
||||||
|
|
||||||
class CheckDangerousFunctions : public Check
|
class CheckDangerousFunctions : public Check
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -52,9 +56,11 @@ public:
|
||||||
void dangerousFunctions();
|
void dangerousFunctions();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** Error Messages.. */
|
/** Report Error : Using dangerous function 'mktemp' */
|
||||||
void dangerousFunctionmktemp(const Token *tok);
|
void dangerousFunctionmktemp(const Token *tok);
|
||||||
|
/** Report Error : Using dangerous function 'gets' */
|
||||||
void dangerousFunctiongets(const Token *tok);
|
void dangerousFunctiongets(const Token *tok);
|
||||||
|
/** Report Error : Using dangerous function 'scanf' */
|
||||||
void dangerousFunctionscanf(const Token *tok);
|
void dangerousFunctionscanf(const Token *tok);
|
||||||
|
|
||||||
void getErrorMessages()
|
void getErrorMessages()
|
||||||
|
|
|
@ -2683,15 +2683,16 @@ void CheckMemoryLeakStructMember::check()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** @brief Experimental class for detecting memory leaks. The ExecutionPath functionality is used */
|
||||||
class CheckLocalLeaks : public ExecutionPath
|
class CheckLocalLeaks : public ExecutionPath
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// Startup constructor
|
/** Startup constructor */
|
||||||
CheckLocalLeaks(Check *c) : ExecutionPath(c, 0), allocated(false)
|
CheckLocalLeaks(Check *c) : ExecutionPath(c, 0), allocated(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Debugging : print checks */
|
||||||
static void printOut(const std::list<ExecutionPath *> &checks)
|
static void printOut(const std::list<ExecutionPath *> &checks)
|
||||||
{
|
{
|
||||||
std::ostringstream ostr;
|
std::ostringstream ostr;
|
||||||
|
@ -2718,12 +2719,16 @@ private:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Is variable allocated? */
|
||||||
bool allocated;
|
bool allocated;
|
||||||
|
|
||||||
|
/** Name of variable */
|
||||||
const std::string varname;
|
const std::string varname;
|
||||||
|
|
||||||
/* no implementation */
|
/** no implementation => compiler error if used */
|
||||||
void operator=(const CheckLocalLeaks &);
|
void operator=(const CheckLocalLeaks &);
|
||||||
|
|
||||||
|
/** Allocation is detected */
|
||||||
static void alloc(std::list<ExecutionPath *> &checks, const unsigned int varid)
|
static void alloc(std::list<ExecutionPath *> &checks, const unsigned int varid)
|
||||||
{
|
{
|
||||||
if (varid == 0)
|
if (varid == 0)
|
||||||
|
@ -2738,6 +2743,7 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Deallocation is detected */
|
||||||
static void dealloc(std::list<ExecutionPath *> &checks, const Token *tok)
|
static void dealloc(std::list<ExecutionPath *> &checks, const Token *tok)
|
||||||
{
|
{
|
||||||
if (tok->varId() == 0)
|
if (tok->varId() == 0)
|
||||||
|
@ -2752,6 +2758,7 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** return */
|
||||||
static void ret(const std::list<ExecutionPath *> &checks, const Token *tok, bool &foundError)
|
static void ret(const std::list<ExecutionPath *> &checks, const Token *tok, bool &foundError)
|
||||||
{
|
{
|
||||||
std::list<ExecutionPath *>::const_iterator it;
|
std::list<ExecutionPath *>::const_iterator it;
|
||||||
|
@ -2771,6 +2778,7 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** parse the tokens */
|
||||||
const Token *parse(const Token &tok, bool &foundError, std::list<ExecutionPath *> &checks) const
|
const Token *parse(const Token &tok, bool &foundError, std::list<ExecutionPath *> &checks) const
|
||||||
{
|
{
|
||||||
//std::cout << "CheckLocalLeaks::parse " << tok.str() << std::endl;
|
//std::cout << "CheckLocalLeaks::parse " << tok.str() << std::endl;
|
||||||
|
|
|
@ -1408,16 +1408,24 @@ static void parseFunctionCall(const Token &tok, std::list<const Token *> &var, u
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// @addtogroup Checks
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief %Check for null pointer usage (using ExecutionPath)
|
||||||
|
*/
|
||||||
|
|
||||||
class CheckNullpointer : public ExecutionPath
|
class CheckNullpointer : public ExecutionPath
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// Startup constructor
|
/** Startup constructor */
|
||||||
CheckNullpointer(Check *c) : ExecutionPath(c, 0), null(false)
|
CheckNullpointer(Check *c) : ExecutionPath(c, 0), null(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Create checking of specific variable:
|
/** Create checking of specific variable: */
|
||||||
CheckNullpointer(Check *c, const unsigned int id, const std::string &name)
|
CheckNullpointer(Check *c, const unsigned int id, const std::string &name)
|
||||||
: ExecutionPath(c, id),
|
: ExecutionPath(c, id),
|
||||||
varname(name),
|
varname(name),
|
||||||
|
@ -1425,17 +1433,22 @@ private:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Copy this check */
|
||||||
ExecutionPath *copy()
|
ExecutionPath *copy()
|
||||||
{
|
{
|
||||||
return new CheckNullpointer(*this);
|
return new CheckNullpointer(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* no implementation */
|
/** no implementation => compiler error if used by accident */
|
||||||
void operator=(const CheckNullpointer &);
|
void operator=(const CheckNullpointer &);
|
||||||
|
|
||||||
|
/** variable name for this check (empty => dummy check) */
|
||||||
const std::string varname;
|
const std::string varname;
|
||||||
|
|
||||||
|
/** is this variable null? */
|
||||||
bool null;
|
bool null;
|
||||||
|
|
||||||
|
/** variable is set to null */
|
||||||
static void setnull(std::list<ExecutionPath *> &checks, const unsigned int varid)
|
static void setnull(std::list<ExecutionPath *> &checks, const unsigned int varid)
|
||||||
{
|
{
|
||||||
std::list<ExecutionPath *>::iterator it;
|
std::list<ExecutionPath *>::iterator it;
|
||||||
|
@ -1447,6 +1460,7 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** variable is dereferenced. If the variable is null there's an error */
|
||||||
static void dereference(bool &foundError, std::list<ExecutionPath *> &checks, const Token *tok)
|
static void dereference(bool &foundError, std::list<ExecutionPath *> &checks, const Token *tok)
|
||||||
{
|
{
|
||||||
const unsigned int varid(tok->varId());
|
const unsigned int varid(tok->varId());
|
||||||
|
@ -1468,6 +1482,7 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** parse tokens */
|
||||||
const Token *parse(const Token &tok, bool &foundError, std::list<ExecutionPath *> &checks) const
|
const Token *parse(const Token &tok, bool &foundError, std::list<ExecutionPath *> &checks) const
|
||||||
{
|
{
|
||||||
if (Token::Match(tok.previous(), "[;{}] %type% * %var% ;"))
|
if (Token::Match(tok.previous(), "[;{}] %type% * %var% ;"))
|
||||||
|
@ -1550,6 +1565,7 @@ private:
|
||||||
return &tok;
|
return &tok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** parse condition. @sa ExecutionPath::parseCondition */
|
||||||
bool parseCondition(const Token &tok, std::list<ExecutionPath *> &checks)
|
bool parseCondition(const Token &tok, std::list<ExecutionPath *> &checks)
|
||||||
{
|
{
|
||||||
if (Token::Match(&tok, "!| %var% ("))
|
if (Token::Match(&tok, "!| %var% ("))
|
||||||
|
@ -1566,38 +1582,50 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief %Check that uninitialized variables aren't used (using ExecutionPath)
|
||||||
|
* */
|
||||||
class CheckUninitVar : public ExecutionPath
|
class CheckUninitVar : public ExecutionPath
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// Startup constructor
|
/** Startup constructor */
|
||||||
CheckUninitVar(Check *c)
|
CheckUninitVar(Check *c)
|
||||||
: ExecutionPath(c, 0), pointer(false), array(false), alloc(false), strncpy_(false)
|
: ExecutionPath(c, 0), pointer(false), array(false), alloc(false), strncpy_(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/** Create a copy of this check */
|
||||||
ExecutionPath *copy()
|
ExecutionPath *copy()
|
||||||
{
|
{
|
||||||
return new CheckUninitVar(*this);
|
return new CheckUninitVar(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* no implementation */
|
/** no implementation => compiler error if used */
|
||||||
void operator=(const CheckUninitVar &);
|
void operator=(const CheckUninitVar &);
|
||||||
|
|
||||||
// internal constructor for creating extra checks
|
/** internal constructor for creating extra checks */
|
||||||
CheckUninitVar(Check *c, unsigned int v, const std::string &name, bool p, bool a)
|
CheckUninitVar(Check *c, unsigned int v, const std::string &name, bool p, bool a)
|
||||||
: ExecutionPath(c, v), varname(name), pointer(p), array(a), alloc(false), strncpy_(false)
|
: ExecutionPath(c, v), varname(name), pointer(p), array(a), alloc(false), strncpy_(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** variable name for this check */
|
||||||
const std::string varname;
|
const std::string varname;
|
||||||
|
|
||||||
|
/** is this variable a pointer? */
|
||||||
const bool pointer;
|
const bool pointer;
|
||||||
|
|
||||||
|
/** is this variable an array? */
|
||||||
const bool array;
|
const bool array;
|
||||||
|
|
||||||
|
/** is this variable allocated? */
|
||||||
bool alloc;
|
bool alloc;
|
||||||
|
|
||||||
|
/** is this variable initialized with strncpy (not always zero-terminated) */
|
||||||
bool strncpy_;
|
bool strncpy_;
|
||||||
|
|
||||||
// p = malloc ..
|
/** allocating pointer. For example : p = malloc(10); */
|
||||||
static void alloc_pointer(std::list<ExecutionPath *> &checks, unsigned int varid)
|
static void alloc_pointer(std::list<ExecutionPath *> &checks, unsigned int varid)
|
||||||
{
|
{
|
||||||
std::list<ExecutionPath *>::const_iterator it;
|
std::list<ExecutionPath *>::const_iterator it;
|
||||||
|
@ -1609,7 +1637,7 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// *p = ..
|
/** Initializing a pointer value. For example: *p = 0; */
|
||||||
static void init_pointer(bool &foundError, std::list<ExecutionPath *> &checks, const Token *tok)
|
static void init_pointer(bool &foundError, std::list<ExecutionPath *> &checks, const Token *tok)
|
||||||
{
|
{
|
||||||
const unsigned int varid(tok->varId());
|
const unsigned int varid(tok->varId());
|
||||||
|
@ -1638,7 +1666,7 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// free p;
|
/** Deallocate a pointer. For example: free(p); */
|
||||||
static void dealloc_pointer(bool &foundError, std::list<ExecutionPath *> &checks, const Token *tok)
|
static void dealloc_pointer(bool &foundError, std::list<ExecutionPath *> &checks, const Token *tok)
|
||||||
{
|
{
|
||||||
const unsigned int varid(tok->varId());
|
const unsigned int varid(tok->varId());
|
||||||
|
@ -1825,6 +1853,7 @@ private:
|
||||||
use(foundError, checks, tok, 3);
|
use(foundError, checks, tok, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** declaring a variable */
|
||||||
void declare(std::list<ExecutionPath *> &checks, const Token *vartok, const Token &tok, const bool p, const bool a) const
|
void declare(std::list<ExecutionPath *> &checks, const Token *vartok, const Token &tok, const bool p, const bool a) const
|
||||||
{
|
{
|
||||||
if (vartok->varId() == 0)
|
if (vartok->varId() == 0)
|
||||||
|
@ -1868,6 +1897,7 @@ private:
|
||||||
checks.push_back(new CheckUninitVar(owner, vartok->varId(), vartok->str(), p, a));
|
checks.push_back(new CheckUninitVar(owner, vartok->varId(), vartok->str(), p, a));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** parse tokens. @sa ExecutionPath::parse */
|
||||||
const Token *parse(const Token &tok, bool &foundError, std::list<ExecutionPath *> &checks) const
|
const Token *parse(const Token &tok, bool &foundError, std::list<ExecutionPath *> &checks) const
|
||||||
{
|
{
|
||||||
// Variable declaration..
|
// Variable declaration..
|
||||||
|
@ -2210,6 +2240,7 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/** Functions that don't handle uninitialized variables well */
|
||||||
static std::set<std::string> uvarFunctions;
|
static std::set<std::string> uvarFunctions;
|
||||||
|
|
||||||
static void analyseFunctions(const Token * const tokens, std::set<std::string> &func)
|
static void analyseFunctions(const Token * const tokens, std::set<std::string> &func)
|
||||||
|
@ -2254,9 +2285,13 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Functions that don't handle uninitialized variables well */
|
||||||
std::set<std::string> CheckUninitVar::uvarFunctions;
|
std::set<std::string> CheckUninitVar::uvarFunctions;
|
||||||
|
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
void CheckOther::analyseFunctions(const Token * const tokens, std::set<std::string> &func)
|
void CheckOther::analyseFunctions(const Token * const tokens, std::set<std::string> &func)
|
||||||
{
|
{
|
||||||
CheckUninitVar::analyseFunctions(tokens, func);
|
CheckUninitVar::analyseFunctions(tokens, func);
|
||||||
|
|
Loading…
Reference in New Issue