returning pointer to local array

This commit is contained in:
Daniel Marjamäki 2009-02-04 18:49:19 +00:00
parent bd73d0913f
commit aeb573d529
5 changed files with 95 additions and 0 deletions

View File

@ -21,6 +21,7 @@
//---------------------------------------------------------------------------
#include "checkother.h"
#include "errormessage.h"
#include <algorithm>
#include <list>
#include <map>
#include <sstream>
@ -813,3 +814,55 @@ 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())
{
if (!infunc && Token::simpleMatch(tok, ") {"))
{
infunc = true;
indentlevel = 0;
arrayVar.clear();
}
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())
ErrorMessage::returnLocalVariable(_errorLogger, _tokenizer, tok);
}
}
// Declaring array variable..
}
}

View File

@ -65,6 +65,9 @@ public:
/** str plus char */
void strPlusChar();
/** Returning pointer to local data */
void returnPointerToStackData();
#ifndef UNIT_TESTING
private:
#endif

View File

@ -332,5 +332,14 @@ public:
return true;
}
static void returnLocalVariable(ErrorLogger *logger, const Tokenizer *tokenizer, const Token *Location)
{
_writemsg(logger, tokenizer, Location, "always", "Returning pointer to local array variable", "returnLocalVariable");
}
static bool returnLocalVariable()
{
return true;
}
};
#endif

View File

@ -48,6 +48,8 @@ private:
TEST_CASE(strPlusChar1); // "/usr" + '/'
TEST_CASE(strPlusChar2); // "/usr" + ch
TEST_CASE(strPlusChar3); // ok: path + "/sub" + '/'
TEST_CASE(returnLocalVariable1);
}
void check(const char code[])
@ -230,6 +232,33 @@ private:
ASSERT_EQUALS(std::string(""), errout.str());
}
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..
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(std::string("[test.cpp:4]: (always) Returning pointer to local array variable\n"), errout.str());
}
};
REGISTER_TEST(TestOther)

View File

@ -102,6 +102,7 @@ int main()
err.push_back(Message("variableScope", Message::never, "The scope of the variable %1 can be limited", "varname"));
err.push_back(Message("conditionAlwaysTrueFalse", Message::style, "Condition is always %1", "truefalse"));
err.push_back(Message("strPlusChar", Message::always, "Unusual pointer arithmetic"));
err.push_back(Message("returnLocalVariable", Message::always, "Returning pointer to local array variable"));
// Generate code..
std::cout << "Generate code.." << std::endl;