possible null pointer dereference after a while-loop

This commit is contained in:
Daniel Marjamäki 2009-03-27 17:19:34 +01:00
parent 063f59c86c
commit c0b608059a
3 changed files with 102 additions and 0 deletions

View File

@ -908,6 +908,60 @@ void CheckOther::returnPointerToStackData()
} }
void CheckOther::nullPointer()
{
// Locate insufficient null-pointer handling after loop
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
{
if (! Token::Match(tok, "while ( %var% )"))
continue;
const unsigned int varid(tok->tokAt(2)->varId());
if (varid == 0)
continue;
// Locate the end of the while loop..
const Token *tok2 = tok->tokAt(4);
int indentlevel = 0;
while (tok2)
{
if (tok2->str() == "{")
++indentlevel;
else if (tok2->str() == "}")
{
if (indentlevel <= 1)
break;
--indentlevel;
}
else if (indentlevel == 0 && tok2->str() == ";")
break;
tok2 = tok2->next();
}
// Goto next token
tok2 = tok2 ? tok2->next() : 0;
// Check if the variable is dereferenced..
while (tok2)
{
if (tok2->str() == "{" || tok2->str() == "}")
break;
if (tok2->varId() == varid)
{
if (tok2->next()->str() == "." || Token::Match(tok2->next(), "= %varid% .", varid))
nullPointerError(tok2);
break;
}
tok2 = tok2->next();
}
}
}
void CheckOther::cstyleCastError(const Token *tok) void CheckOther::cstyleCastError(const Token *tok)
{ {
reportError(tok, "style", "cstyleCast", "C-style pointer casting"); reportError(tok, "style", "cstyleCast", "C-style pointer casting");
@ -992,3 +1046,8 @@ void CheckOther::returnLocalVariable(const Token *tok)
{ {
reportError(tok, "error", "returnLocalVariable", "Returning pointer to local array variable"); reportError(tok, "error", "returnLocalVariable", "Returning pointer to local array variable");
} }
void CheckOther::nullPointerError(const Token *tok)
{
reportError(tok, "error", "nullPointer", "Possible null pointer dereference");
}

View File

@ -70,6 +70,7 @@ public:
checkOther.strPlusChar(); checkOther.strPlusChar();
checkOther.returnPointerToStackData(); checkOther.returnPointerToStackData();
checkOther.InvalidFunctionUsage(); checkOther.InvalidFunctionUsage();
checkOther.nullPointer();
} }
// Casting // Casting
@ -108,6 +109,9 @@ public:
/** Returning pointer to local data */ /** Returning pointer to local data */
void returnPointerToStackData(); void returnPointerToStackData();
/** possible null pointer dereference */
void nullPointer();
protected: protected:
void CheckVariableScope_LookupVar(const Token *tok1, const char varname[]); void CheckVariableScope_LookupVar(const Token *tok1, const char varname[]);
@ -135,6 +139,7 @@ private:
void conditionAlwaysTrueFalse(const Token *tok, const std::string &truefalse); void conditionAlwaysTrueFalse(const Token *tok, const std::string &truefalse);
void strPlusChar(const Token *tok); void strPlusChar(const Token *tok);
void returnLocalVariable(const Token *tok); void returnLocalVariable(const Token *tok);
void nullPointerError(const Token *tok);
void getErrorMessages() void getErrorMessages()
{ {
@ -155,6 +160,7 @@ private:
conditionAlwaysTrueFalse(0, "true/false"); conditionAlwaysTrueFalse(0, "true/false");
strPlusChar(0); strPlusChar(0);
returnLocalVariable(0); returnLocalVariable(0);
nullPointerError(0);
} }
}; };

View File

@ -53,6 +53,8 @@ private:
TEST_CASE(varScope1); TEST_CASE(varScope1);
TEST_CASE(varScope2); TEST_CASE(varScope2);
TEST_CASE(nullpointer1);
} }
void check(const char code[]) void check(const char code[])
@ -71,6 +73,9 @@ private:
checkOther.WarningRedundantCode(); checkOther.WarningRedundantCode();
} }
void delete1() void delete1()
{ {
check("void foo()\n" check("void foo()\n"
@ -326,6 +331,38 @@ private:
"}\n"); "}\n");
ASSERT_EQUALS(std::string(""), errout.str()); ASSERT_EQUALS(std::string(""), errout.str());
} }
void checkNullPointer(const char code[])
{
// Tokenize..
Tokenizer tokenizer;
std::istringstream istr(code);
tokenizer.tokenize(istr, "test.cpp");
tokenizer.setVarId();
// Clear the error buffer..
errout.str("");
// Check for redundant code..
Settings settings;
settings._checkCodingStyle = true;
CheckOther checkOther(&tokenizer, &settings, this);
checkOther.nullPointer();
}
void nullpointer1()
{
checkNullPointer("int foo(const Token *tok)\n"
"{\n"
" while (tok);\n"
" tok = tok->next();\n"
"}\n");
ASSERT_EQUALS(std::string("[test.cpp:4]: (error) Possible null pointer dereference\n"), errout.str());
}
}; };
REGISTER_TEST(TestOther) REGISTER_TEST(TestOther)