Merge branch 'master' of git@github.com:danmar/cppcheck

This commit is contained in:
Slava Semushin 2009-06-10 01:56:26 +07:00
commit fe5d0c56ba
6 changed files with 102 additions and 114 deletions

View File

@ -223,4 +223,70 @@ void CheckAutoVariables::autoVariables()
void CheckAutoVariables::returnPointerToLocalArray()
{
bool infunc = false;
int indentlevel = 0;
std::list<unsigned int> arrayVar;
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
{
// Is there a function declaration for a function that returns a pointer?
if (!infunc && (Token::Match(tok, "%type% * %var% (") || Token::Match(tok, "%type% * %var% :: %var% (")))
{
for (const Token *tok2 = tok; tok2; tok2 = tok2->next())
{
if (tok2->str() == ")")
{
tok = tok2;
break;
}
}
if (Token::simpleMatch(tok, ") {"))
{
infunc = true;
indentlevel = 0;
arrayVar.clear();
}
}
// Parsing a function that returns a pointer..
if (infunc)
{
if (tok->str() == "{")
++indentlevel;
else if (tok->str() == "}")
{
--indentlevel;
if (indentlevel <= 0)
infunc = false;
continue;
}
// Declaring a local array..
if (Token::Match(tok, "[;{}] %type% %var% ["))
{
arrayVar.push_back(tok->tokAt(2)->varId());
}
// Return pointer to local array variable..
if (Token::Match(tok, "return %var% ;"))
{
unsigned int varid = tok->next()->varId();
if (varid > 0 && std::find(arrayVar.begin(), arrayVar.end(), varid) != arrayVar.end())
errorReturnPointerToLocalArray(tok);
}
}
// Declaring array variable..
}
}
void CheckAutoVariables::errorReturnPointerToLocalArray(const Token *tok)
{
reportError(tok, "error", "returnLocalVariable", "Returning pointer to local array variable");
}

View File

@ -42,11 +42,15 @@ public:
{
CheckAutoVariables checkAutoVariables(tokenizer, settings, errorLogger);
checkAutoVariables.autoVariables();
checkAutoVariables.returnPointerToLocalArray();
}
/** Check auto variables */
void autoVariables();
/** Returning pointer to local array */
void returnPointerToLocalArray();
private:
std::list<std::string> fp_list;
std::list<std::string> vd_list;
@ -54,10 +58,17 @@ private:
bool isAutoVar(const Token* t);
void addVD(const Token* t);
void errorReturnPointerToLocalArray(const Token *tok);
void getErrorMessages()
{
std::cout << "===auto variables===" << "\n";
reportError(0, "error", "autoVariables", "Wrong assignement of an auto-variable to an effective parameter of a function");
errorReturnPointerToLocalArray(0);
}
};

View File

@ -864,68 +864,6 @@ void CheckOther::strPlusChar()
void CheckOther::returnPointerToStackData()
{
bool infunc = false;
int indentlevel = 0;
std::list<unsigned int> arrayVar;
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
{
// Is there a function declaration for a function that returns a pointer?
if (!infunc && (Token::Match(tok, "%type% * %var% (") || Token::Match(tok, "%type% * %var% :: %var% (")))
{
for (const Token *tok2 = tok; tok2; tok2 = tok2->next())
{
if (tok2->str() == ")")
{
tok = tok2;
break;
}
}
if (Token::simpleMatch(tok, ") {"))
{
infunc = true;
indentlevel = 0;
arrayVar.clear();
}
}
// Parsing a function that returns a pointer..
if (infunc)
{
if (tok->str() == "{")
++indentlevel;
else if (tok->str() == "}")
{
--indentlevel;
if (indentlevel <= 0)
infunc = false;
continue;
}
// Declaring a local array..
if (Token::Match(tok, "[;{}] %type% %var% ["))
{
arrayVar.push_back(tok->tokAt(2)->varId());
}
// Return pointer to local array variable..
if (Token::Match(tok, "return %var% ;"))
{
unsigned int varid = tok->next()->varId();
if (varid > 0 && std::find(arrayVar.begin(), arrayVar.end(), varid) != arrayVar.end())
returnLocalVariable(tok);
}
}
// Declaring array variable..
}
}
void CheckOther::nullPointer()
{
// Locate insufficient null-pointer handling after loop
@ -1083,11 +1021,6 @@ void CheckOther::strPlusChar(const Token *tok)
reportError(tok, "error", "strPlusChar", "Unusual pointer arithmetic");
}
void CheckOther::returnLocalVariable(const Token *tok)
{
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

@ -67,7 +67,6 @@ public:
}
checkOther.strPlusChar();
checkOther.returnPointerToStackData();
checkOther.InvalidFunctionUsage();
checkOther.nullPointer();
checkOther.CheckZeroDivision();
@ -106,9 +105,6 @@ public:
/** str plus char */
void strPlusChar();
/** Returning pointer to local data */
void returnPointerToStackData();
/** possible null pointer dereference */
void nullPointer();
@ -141,7 +137,6 @@ private:
void variableScopeError(const Token *tok, const std::string &varname);
void conditionAlwaysTrueFalse(const Token *tok, const std::string &truefalse);
void strPlusChar(const Token *tok);
void returnLocalVariable(const Token *tok);
void nullPointerError(const Token *tok);
void zerodivError(const Token *tok);
@ -164,7 +159,6 @@ private:
variableScopeError(0, "varname");
conditionAlwaysTrueFalse(0, "true/false");
strPlusChar(0);
returnLocalVariable(0);
nullPointerError(0);
zerodivError(0);
}

View File

@ -54,9 +54,9 @@ private:
// Check auto variables
Settings settings;
settings._showAll = true;
CheckAutoVariables checkAutoVariables(&tokenizer, &settings, this);
checkAutoVariables.autoVariables();
checkAutoVariables.returnPointerToLocalArray();
}
void run()
@ -64,6 +64,9 @@ private:
TEST_CASE(testautovar);
TEST_CASE(testautovararray);
TEST_CASE(testautovarreturn);
TEST_CASE(returnLocalVariable1);
TEST_CASE(returnLocalVariable2);
}
@ -99,6 +102,27 @@ private:
"return &num;}");
ASSERT_EQUALS("[test.cpp:3]: (error) Return of the address of an auto-variable\n", errout.str());
}
void returnLocalVariable1()
{
check("char *foo()\n"
"{\n"
" char str[100] = {0};\n"
" return str;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Returning pointer to local array variable\n", errout.str());
}
void returnLocalVariable2()
{
check("std::string foo()\n"
"{\n"
" char str[100] = {0};\n"
" return str;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
};
REGISTER_TEST(TestAutoVariables)

View File

@ -51,9 +51,6 @@ private:
TEST_CASE(strPlusChar2); // "/usr" + ch
TEST_CASE(strPlusChar3); // ok: path + "/sub" + '/'
TEST_CASE(returnLocalVariable1);
TEST_CASE(returnLocalVariable2);
TEST_CASE(varScope1);
TEST_CASE(varScope2);
TEST_CASE(varScope3);
@ -302,43 +299,6 @@ private:
void retVar(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;
CheckOther checkOther(&tokenizer, &settings, this);
checkOther.returnPointerToStackData();
}
void returnLocalVariable1()
{
retVar("char *foo()\n"
"{\n"
" char str[100] = {0};\n"
" return str;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Returning pointer to local array variable\n", errout.str());
}
void returnLocalVariable2()
{
retVar("std::string foo()\n"
"{\n"
" char str[100] = {0};\n"
" return str;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
void varScope(const char code[])
{
// Tokenize..