diff --git a/lib/checkbufferoverrun.h b/lib/checkbufferoverrun.h index 71c23984e..2c7a70c03 100644 --- a/lib/checkbufferoverrun.h +++ b/lib/checkbufferoverrun.h @@ -35,7 +35,15 @@ class Tokenizer; /// @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 { public: @@ -55,14 +63,21 @@ public: checkBufferOverrun.bufferOverrun(); } - /** Check for buffer overruns */ + /** @brief %Check for buffer overruns */ 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 ¶meters); 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. * @param tok The "sprintf" token. * @param size The size of the buffer where sprintf is writing. diff --git a/lib/checkclass.h b/lib/checkclass.h index c57e7a482..cd91ddc3e 100644 --- a/lib/checkclass.h +++ b/lib/checkclass.h @@ -43,12 +43,16 @@ public: : Check(tokenizer, settings, errorLogger) { } + /** @brief Run checks on the normal token list */ void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) { CheckClass checkClass(tokenizer, settings, errorLogger); + + // can't be a simplified check .. the 'sizeof' is used. checkClass.noMemset(); } + /** @brief Run checks on the simplified token list */ void runSimplifiedChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) { CheckClass checkClass(tokenizer, settings, errorLogger); @@ -78,7 +82,10 @@ public: /** * @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. */ void noMemset(); diff --git a/lib/checkdangerousfunctions.h b/lib/checkdangerousfunctions.h index 98dacae68..fe93357ce 100644 --- a/lib/checkdangerousfunctions.h +++ b/lib/checkdangerousfunctions.h @@ -27,6 +27,10 @@ /// @addtogroup Checks /// @{ +/** + * @brief Using dangerous functions that are always insecure to use. + */ + class CheckDangerousFunctions : public Check { public: @@ -52,9 +56,11 @@ public: void dangerousFunctions(); private: - /** Error Messages.. */ + /** Report Error : Using dangerous function 'mktemp' */ void dangerousFunctionmktemp(const Token *tok); + /** Report Error : Using dangerous function 'gets' */ void dangerousFunctiongets(const Token *tok); + /** Report Error : Using dangerous function 'scanf' */ void dangerousFunctionscanf(const Token *tok); void getErrorMessages() diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index f4ec46db9..f5ccd93e3 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -2683,15 +2683,16 @@ void CheckMemoryLeakStructMember::check() - +/** @brief Experimental class for detecting memory leaks. The ExecutionPath functionality is used */ class CheckLocalLeaks : public ExecutionPath { public: - // Startup constructor + /** Startup constructor */ CheckLocalLeaks(Check *c) : ExecutionPath(c, 0), allocated(false) { } + /** Debugging : print checks */ static void printOut(const std::list &checks) { std::ostringstream ostr; @@ -2718,12 +2719,16 @@ private: { } + /** Is variable allocated? */ bool allocated; + + /** Name of variable */ const std::string varname; - /* no implementation */ + /** no implementation => compiler error if used */ void operator=(const CheckLocalLeaks &); + /** Allocation is detected */ static void alloc(std::list &checks, const unsigned int varid) { if (varid == 0) @@ -2738,6 +2743,7 @@ private: } } + /** Deallocation is detected */ static void dealloc(std::list &checks, const Token *tok) { if (tok->varId() == 0) @@ -2752,6 +2758,7 @@ private: } } + /** return */ static void ret(const std::list &checks, const Token *tok, bool &foundError) { std::list::const_iterator it; @@ -2771,6 +2778,7 @@ private: } } + /** parse the tokens */ const Token *parse(const Token &tok, bool &foundError, std::list &checks) const { //std::cout << "CheckLocalLeaks::parse " << tok.str() << std::endl; diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 16b33c702..26bd32bff 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -1408,16 +1408,24 @@ static void parseFunctionCall(const Token &tok, std::list &var, u } +/// @addtogroup Checks +/// @{ + + +/** + * @brief %Check for null pointer usage (using ExecutionPath) + */ + class CheckNullpointer : public ExecutionPath { public: - // Startup constructor + /** Startup constructor */ CheckNullpointer(Check *c) : ExecutionPath(c, 0), null(false) { } private: - // Create checking of specific variable: + /** Create checking of specific variable: */ CheckNullpointer(Check *c, const unsigned int id, const std::string &name) : ExecutionPath(c, id), varname(name), @@ -1425,17 +1433,22 @@ private: { } + /** Copy this check */ ExecutionPath *copy() { return new CheckNullpointer(*this); } - /* no implementation */ + /** no implementation => compiler error if used by accident */ void operator=(const CheckNullpointer &); + /** variable name for this check (empty => dummy check) */ const std::string varname; + + /** is this variable null? */ bool null; + /** variable is set to null */ static void setnull(std::list &checks, const unsigned int varid) { std::list::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 &checks, const Token *tok) { const unsigned int varid(tok->varId()); @@ -1468,6 +1482,7 @@ private: } } + /** parse tokens */ const Token *parse(const Token &tok, bool &foundError, std::list &checks) const { if (Token::Match(tok.previous(), "[;{}] %type% * %var% ;")) @@ -1550,6 +1565,7 @@ private: return &tok; } + /** parse condition. @sa ExecutionPath::parseCondition */ bool parseCondition(const Token &tok, std::list &checks) { if (Token::Match(&tok, "!| %var% (")) @@ -1566,38 +1582,50 @@ private: }; - +/** + * @brief %Check that uninitialized variables aren't used (using ExecutionPath) + * */ class CheckUninitVar : public ExecutionPath { public: - // Startup constructor + /** Startup constructor */ CheckUninitVar(Check *c) : ExecutionPath(c, 0), pointer(false), array(false), alloc(false), strncpy_(false) { } private: + /** Create a copy of this check */ ExecutionPath *copy() { return new CheckUninitVar(*this); } - /* no implementation */ + /** no implementation => compiler error if used */ 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) : ExecutionPath(c, v), varname(name), pointer(p), array(a), alloc(false), strncpy_(false) { } + /** variable name for this check */ const std::string varname; + + /** is this variable a pointer? */ const bool pointer; + + /** is this variable an array? */ const bool array; + + /** is this variable allocated? */ bool alloc; + + /** is this variable initialized with strncpy (not always zero-terminated) */ bool strncpy_; - // p = malloc .. + /** allocating pointer. For example : p = malloc(10); */ static void alloc_pointer(std::list &checks, unsigned int varid) { std::list::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 &checks, const Token *tok) { 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 &checks, const Token *tok) { const unsigned int varid(tok->varId()); @@ -1825,6 +1853,7 @@ private: use(foundError, checks, tok, 3); } + /** declaring a variable */ void declare(std::list &checks, const Token *vartok, const Token &tok, const bool p, const bool a) const { if (vartok->varId() == 0) @@ -1868,6 +1897,7 @@ private: 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 &checks) const { // Variable declaration.. @@ -2210,6 +2240,7 @@ private: public: + /** Functions that don't handle uninitialized variables well */ static std::set uvarFunctions; static void analyseFunctions(const Token * const tokens, std::set &func) @@ -2254,9 +2285,13 @@ public: } }; +/** Functions that don't handle uninitialized variables well */ std::set CheckUninitVar::uvarFunctions; +/// @} + + void CheckOther::analyseFunctions(const Token * const tokens, std::set &func) { CheckUninitVar::analyseFunctions(tokens, func);