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 checkAutoVariables(tokenizer, settings, errorLogger);
checkAutoVariables.autoVariables(); checkAutoVariables.autoVariables();
checkAutoVariables.returnPointerToLocalArray();
} }
/** Check auto variables */ /** Check auto variables */
void autoVariables(); void autoVariables();
/** Returning pointer to local array */
void returnPointerToLocalArray();
private: private:
std::list<std::string> fp_list; std::list<std::string> fp_list;
std::list<std::string> vd_list; std::list<std::string> vd_list;
@ -54,10 +58,17 @@ private:
bool isAutoVar(const Token* t); bool isAutoVar(const Token* t);
void addVD(const Token* t); void addVD(const Token* t);
void errorReturnPointerToLocalArray(const Token *tok);
void getErrorMessages() void getErrorMessages()
{ {
std::cout << "===auto variables===" << "\n"; std::cout << "===auto variables===" << "\n";
reportError(0, "error", "autoVariables", "Wrong assignement of an auto-variable to an effective parameter of a function"); 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() void CheckOther::nullPointer()
{ {
// Locate insufficient null-pointer handling after loop // Locate insufficient null-pointer handling after loop
@ -1083,11 +1021,6 @@ void CheckOther::strPlusChar(const Token *tok)
reportError(tok, "error", "strPlusChar", "Unusual pointer arithmetic"); 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) void CheckOther::nullPointerError(const Token *tok)
{ {
reportError(tok, "error", "nullPointer", "Possible null pointer dereference"); reportError(tok, "error", "nullPointer", "Possible null pointer dereference");

View File

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

View File

@ -54,9 +54,9 @@ private:
// Check auto variables // Check auto variables
Settings settings; Settings settings;
settings._showAll = true;
CheckAutoVariables checkAutoVariables(&tokenizer, &settings, this); CheckAutoVariables checkAutoVariables(&tokenizer, &settings, this);
checkAutoVariables.autoVariables(); checkAutoVariables.autoVariables();
checkAutoVariables.returnPointerToLocalArray();
} }
void run() void run()
@ -64,6 +64,9 @@ private:
TEST_CASE(testautovar); TEST_CASE(testautovar);
TEST_CASE(testautovararray); TEST_CASE(testautovararray);
TEST_CASE(testautovarreturn); TEST_CASE(testautovarreturn);
TEST_CASE(returnLocalVariable1);
TEST_CASE(returnLocalVariable2);
} }
@ -99,6 +102,27 @@ private:
"return &num;}"); "return &num;}");
ASSERT_EQUALS("[test.cpp:3]: (error) Return of the address of an auto-variable\n", errout.str()); 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) REGISTER_TEST(TestAutoVariables)

View File

@ -51,9 +51,6 @@ private:
TEST_CASE(strPlusChar2); // "/usr" + ch TEST_CASE(strPlusChar2); // "/usr" + ch
TEST_CASE(strPlusChar3); // ok: path + "/sub" + '/' TEST_CASE(strPlusChar3); // ok: path + "/sub" + '/'
TEST_CASE(returnLocalVariable1);
TEST_CASE(returnLocalVariable2);
TEST_CASE(varScope1); TEST_CASE(varScope1);
TEST_CASE(varScope2); TEST_CASE(varScope2);
TEST_CASE(varScope3); 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[]) void varScope(const char code[])
{ {
// Tokenize.. // Tokenize..