Merge branch 'master' of git@github.com:danmar/cppcheck
This commit is contained in:
commit
fe5d0c56ba
|
@ -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");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 #}");
|
"return #}");
|
||||||
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)
|
||||||
|
|
|
@ -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..
|
||||||
|
|
Loading…
Reference in New Issue