possible null pointer dereference after a while-loop
This commit is contained in:
parent
063f59c86c
commit
c0b608059a
|
@ -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");
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue