diff --git a/lib/checknullpointer.cpp b/lib/checknullpointer.cpp index b69f79e31..18b33c7c4 100644 --- a/lib/checknullpointer.cpp +++ b/lib/checknullpointer.cpp @@ -19,7 +19,6 @@ //--------------------------------------------------------------------------- #include "checknullpointer.h" -#include "executionpath.h" #include "mathlib.h" #include "symboldatabase.h" #include @@ -1038,212 +1037,6 @@ void CheckNullPointer::nullPointerDefaultArgument() /// @{ -/** - * @brief %Check for null pointer usage (using ExecutionPath) - */ - -class Nullpointer : public ExecutionPath { -public: - /** Startup constructor */ - Nullpointer(Check *c, const SymbolDatabase* symbolDatabase_, const Library *lib) : ExecutionPath(c, 0), symbolDatabase(symbolDatabase_), library(lib), null(false) { - } - -private: - const SymbolDatabase* symbolDatabase; - const Library *library; - - /** Create checking of specific variable: */ - Nullpointer(Check *c, const unsigned int id, const std::string &name, const SymbolDatabase* symbolDatabase_, const Library *lib) - : ExecutionPath(c, id), - symbolDatabase(symbolDatabase_), - library(lib), - varname(name), - null(false) { - } - - /** Copy this check */ - ExecutionPath *copy() { - return new Nullpointer(*this); - } - - /** no implementation => compiler error if used by accident */ - void operator=(const Nullpointer &); - - /** is other execution path equal? */ - bool is_equal(const ExecutionPath *e) const { - const Nullpointer *c = static_cast(e); - return (varname == c->varname && null == c->null); - } - - /** 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, bool null) { - std::list::iterator it; - for (it = checks.begin(); it != checks.end(); ++it) { - Nullpointer *c = dynamic_cast(*it); - if (c && c->varId == varid) - c->null = null; - } - } - - /** - * Dereferencing variable. Check if it is safe (if the variable is null there's an error) - * @param checks Checks - * @param tok token where dereferencing happens - */ - static void dereference(std::list &checks, const Token *tok) { - const unsigned int varid(tok->varId()); - - std::list::iterator it; - for (it = checks.begin(); it != checks.end(); ++it) { - Nullpointer *c = dynamic_cast(*it); - if (c && c->varId == varid && c->null) { - for (const Token *tok2 = tok; tok2 && tok2->str() != ";"; tok2 = tok2->previous()) { - // Checking that pointer is not NULL - if (Token::Match(tok2, "return|=|[|(|,|&& %varid% )| &&", varid)) - return; - if (Token::Match(tok2, "return|=|[|(|,|%oror% ! %varid% )| %oror%", varid)) - return; - } - - CheckNullPointer *checkNullPointer = dynamic_cast(c->owner); - if (checkNullPointer) { - checkNullPointer->nullPointerError(tok, c->varname); - return; - } - } - } - } - - /** parse tokens */ - const Token *parse(const Token &tok, std::list &checks) const { - if (tok.varId() != 0) { - // Pointer declaration declaration? - const Variable *var = tok.variable(); - if (var && var->isPointer() && var->nameToken() == &tok) - checks.push_back(new Nullpointer(owner, var->declarationId(), var->name(), symbolDatabase, library)); - } - - if (Token::simpleMatch(&tok, "try {")) { - // Bail out all used variables - const Token* tok2 = &tok; - const Token* endtok = tok.linkAt(1); - for (; tok2 && tok2 != endtok; tok2 = tok2->next()) { - if (tok2->varId()) - bailOutVar(checks,tok2->varId()); - } - return tok2; - } - - if (Token::Match(&tok, "%var% (")) { - if (tok.str() == "sizeof" || tok.str() == "typeid") - return tok.next()->link(); - - // parse usage.. - std::list var; - CheckNullPointer::parseFunctionCall(tok, var, library, 0); - for (std::list::const_iterator it = var.begin(); it != var.end(); ++it) - dereference(checks, *it); - } - - else if (Token::simpleMatch(&tok, "( 0 &&")) - return tok.link(); - - if (tok.varId() != 0) { - // unknown: if isPointerDeRef fails to determine if there - // is a dereference this will be set to true. - bool unknown = owner->inconclusiveFlag(); - bool deref = CheckNullPointer::isPointerDeRef(&tok, unknown); - - if (deref) - dereference(checks, &tok); - else if (unknown && owner->inconclusiveFlag()) - dereference(checks, &tok); - if (Token::Match(tok.previous(), "[;{}=] %var% =")) - setnull(checks, tok.varId(), Token::simpleMatch(tok.tokAt(2), "0 ;")); - else if (!deref && - (!tok.previous()->isOp() || tok.previous()->str() == "&") && - (!tok.next()->isConstOp() || tok.next()->str() == ">>")) - bailOutVar(checks, tok.varId()); // If its possible that the pointers value changes, bail out. - } - - else if (tok.str() == "delete") { - const Token *ret = tok.next(); - if (Token::simpleMatch(ret, "[ ]")) - ret = ret->tokAt(2); - if (Token::Match(ret, "%var% ;")) - return ret->next(); - } - - else if (tok.str() == "return") { - bool unknown = owner->inconclusiveFlag(); - const Token* tok2 = &tok; - for (; tok2 && tok2->str() != ";"; tok2 = tok2->next()) { - if (tok2->varId()) { - if (CheckNullPointer::isPointerDeRef(tok2, unknown) || unknown) - dereference(checks, tok2); - } - - // If return statement contains "?" then assume there - // is no dangours dereferencing later - if (tok2->str() == "?") { - while (tok2 && tok2->str() != ";") - tok2 = tok2->next(); - return tok2; - } - } - } - - return &tok; - } - - /** parse condition. @sa ExecutionPath::parseCondition */ - bool parseCondition(const Token &tok, std::list &checks) { - for (const Token *tok2 = &tok; tok2; tok2 = tok2->next()) { - if (tok2->str() == "(" || tok2->str() == ")" || tok2->str() == "&&" || tok2->str() == "||" || tok2->str() == "?") - break; - bool unknown = owner->inconclusiveFlag(); - if (tok2->varId() && (CheckNullPointer::isPointerDeRef(tok2, unknown) || unknown)) - dereference(checks, tok2); - } - - if (Token::Match(&tok, "!| %var% (")) { - std::list var; - CheckNullPointer::parseFunctionCall(tok.str() == "!" ? *tok.next() : tok, var, library, 0); - for (std::list::const_iterator it = var.begin(); it != var.end(); ++it) - dereference(checks, *it); - } - - return ExecutionPath::parseCondition(tok, checks); - } - - - void parseLoopBody(const Token *tok, std::list &checks) const { - while (tok) { - if (Token::Match(tok, "{|}|return|goto|break|if")) - return; - const Token *next = parse(*tok, checks); - if (next) - tok = tok->next(); - } - } - -}; -/// @} - - -void CheckNullPointer::executionPaths() -{ - // Check for null pointer errors.. - Nullpointer c(this, _tokenizer->getSymbolDatabase(), &_settings->library); - checkExecutionPaths(_tokenizer->getSymbolDatabase(), &c); -} - void CheckNullPointer::nullPointerError(const Token *tok) { reportError(tok, Severity::error, "nullPointer", "Null pointer dereference"); diff --git a/lib/checknullpointer.h b/lib/checknullpointer.h index e08912a36..4d2a67ded 100644 --- a/lib/checknullpointer.h +++ b/lib/checknullpointer.h @@ -56,7 +56,6 @@ public: void runSimplifiedChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) { CheckNullPointer checkNullPointer(tokenizer, settings, errorLogger); checkNullPointer.nullConstantDereference(); - checkNullPointer.executionPaths(); } /** @@ -95,9 +94,6 @@ public: /** @brief dereferencing null constant (after Tokenizer::simplifyKnownVariables) */ void nullConstantDereference(); - /** @brief new type of check: check execution paths */ - void executionPaths(); - void nullPointerError(const Token *tok); // variable name unknown / doesn't exist void nullPointerError(const Token *tok, const std::string &varname, bool inconclusive=false); void nullPointerError(const Token *tok, const std::string &varname, const Token* nullcheck, bool inconclusive = false); diff --git a/test/testnullpointer.cpp b/test/testnullpointer.cpp index 43cabd91e..0bb8a8bdc 100644 --- a/test/testnullpointer.cpp +++ b/test/testnullpointer.cpp @@ -113,7 +113,6 @@ private: "TestSimplifyTokens instead.\nstr1="+str1+"\nstr2="+str2).c_str()); checkNullPointer.nullConstantDereference(); - //checkNullPointer.executionPaths(); }