Auto variables: Assign address of local variable to global pointer (#6825)

This commit is contained in:
Daniel Marjamäki 2018-01-25 22:50:41 +01:00
parent 9109956c8c
commit cb297a00fc
3 changed files with 52 additions and 17 deletions

View File

@ -208,6 +208,22 @@ void CheckAutoVariables::assignFunctionArg()
} }
} }
static bool reassignedGlobalPointer(const Token *vartok, unsigned int pointerVarId)
{
const Token * const end = vartok->variable()->typeStartToken()->scope()->classEnd;
for (const Token *tok2 = vartok; tok2 != nullptr && tok2 != end; tok2 = tok2->next()) {
if (Token::Match(tok2, "%varid% =", pointerVarId))
return true;
if (Token::Match(tok2, "%name% (") && !Token::simpleMatch(tok2->linkAt(1), ") {")) {
// Bailout: possibly written
// TODO: check if it is written
return true;
}
}
return false;
}
void CheckAutoVariables::autoVariables() void CheckAutoVariables::autoVariables()
{ {
const bool printInconclusive = _settings->inconclusive; const bool printInconclusive = _settings->inconclusive;
@ -223,25 +239,17 @@ void CheckAutoVariables::autoVariables()
} else if (Token::Match(tok, "[;{}] * %var% = & %var%") && isPtrArg(tok->tokAt(2)) && isAutoVar(tok->tokAt(5))) { } else if (Token::Match(tok, "[;{}] * %var% = & %var%") && isPtrArg(tok->tokAt(2)) && isAutoVar(tok->tokAt(5))) {
if (checkRvalueExpression(tok->tokAt(5))) if (checkRvalueExpression(tok->tokAt(5)))
errorAutoVariableAssignment(tok->next(), false); errorAutoVariableAssignment(tok->next(), false);
} else if (_settings->isEnabled(Settings::WARNING) && Token::Match(tok, "[;{}] %var% = %var% ;") && isGlobalPtr(tok->next()) && isAutoVarArray(tok->tokAt(3))) { } else if (_settings->isEnabled(Settings::WARNING) && Token::Match(tok, "[;{}] %var% = &| %var% ;") && isGlobalPtr(tok->next())) {
const Token * const pointer = tok->next(); const Token * const pointer = tok->next();
const Token * const array = tok->tokAt(3); if (isAutoVarArray(tok->tokAt(3))) {
const Token * const end = array->variable()->typeStartToken()->scope()->classEnd; const Token * const array = tok->tokAt(3);
const unsigned int varid = pointer->varId(); if (!reassignedGlobalPointer(array, pointer->varId()))
bool writtenAgain = false; errorAssignAddressOfLocalArrayToGlobalPointer(pointer, array);
for (const Token *tok2 = array; tok2 != nullptr && tok2 != end; tok2 = tok2->next()) { } else if (isAutoVar(tok->tokAt(4))) {
if (Token::Match(tok2, "%varid% =", varid)) { const Token * const variable = tok->tokAt(4);
writtenAgain = true; if (!reassignedGlobalPointer(variable, pointer->varId()))
break; errorAssignAddressOfLocalVariableToGlobalPointer(pointer, variable);
} else if (Token::Match(tok2, "%name% (") && !Token::simpleMatch(tok2->linkAt(1), ") {")) {
// Bailout: possibly written
// TODO: check if it is written
writtenAgain = true;
break;
}
} }
if (!writtenAgain)
errorAssignAddressOfLocalArrayToGlobalPointer(pointer, array);
} else if (Token::Match(tok, "[;{}] %var% . %var% = & %var%")) { } else if (Token::Match(tok, "[;{}] %var% . %var% = & %var%")) {
// TODO: check if the parameter is only changed temporarily (#2969) // TODO: check if the parameter is only changed temporarily (#2969)
if (printInconclusive && isPtrArg(tok->next())) { if (printInconclusive && isPtrArg(tok->next())) {
@ -362,6 +370,14 @@ void CheckAutoVariables::errorAssignAddressOfLocalArrayToGlobalPointer(const Tok
"Address of local array " + arrayName + " is assigned to global pointer " + pointerName +" and not reassigned before " + arrayName + " goes out of scope.", CWE562, false); "Address of local array " + arrayName + " is assigned to global pointer " + pointerName +" and not reassigned before " + arrayName + " goes out of scope.", CWE562, false);
} }
void CheckAutoVariables::errorAssignAddressOfLocalVariableToGlobalPointer(const Token *pointer, const Token *variable)
{
const std::string pointerName = pointer ? pointer->str() : std::string("pointer");
const std::string variableName = variable ? variable->str() : std::string("variable");
reportError(pointer, Severity::warning, "autoVariablesAssignGlobalPointer",
"Address of local variable " + variableName + " is assigned to global pointer " + pointerName +" and not reassigned before " + variableName + " goes out of scope.", CWE562, false);
}
void CheckAutoVariables::errorReturnAddressOfFunctionParameter(const Token *tok, const std::string &varname) void CheckAutoVariables::errorReturnAddressOfFunctionParameter(const Token *tok, const std::string &varname)
{ {
reportError(tok, Severity::error, "returnAddressOfFunctionParameter", reportError(tok, Severity::error, "returnAddressOfFunctionParameter",

View File

@ -83,6 +83,7 @@ private:
void errorReturnAddressToAutoVariable(const Token *tok); void errorReturnAddressToAutoVariable(const Token *tok);
void errorAssignAddressOfLocalArrayToGlobalPointer(const Token *pointer, const Token *array); void errorAssignAddressOfLocalArrayToGlobalPointer(const Token *pointer, const Token *array);
void errorAssignAddressOfLocalVariableToGlobalPointer(const Token *pointer, const Token *variable);
void errorReturnPointerToLocalArray(const Token *tok); void errorReturnPointerToLocalArray(const Token *tok);
void errorAutoVariableAssignment(const Token *tok, bool inconclusive); void errorAutoVariableAssignment(const Token *tok, bool inconclusive);
void errorReturnReference(const Token *tok); void errorReturnReference(const Token *tok);

View File

@ -88,6 +88,7 @@ private:
TEST_CASE(testassign2); // Ticket #2765 TEST_CASE(testassign2); // Ticket #2765
TEST_CASE(assignAddressOfLocalArrayToGlobalPointer); TEST_CASE(assignAddressOfLocalArrayToGlobalPointer);
TEST_CASE(assignAddressOfLocalVariableToGlobalPointer);
TEST_CASE(returnLocalVariable1); TEST_CASE(returnLocalVariable1);
TEST_CASE(returnLocalVariable2); TEST_CASE(returnLocalVariable2);
@ -642,6 +643,23 @@ private:
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void assignAddressOfLocalVariableToGlobalPointer() {
check("int *p;\n"
"void f() {\n"
" int x;\n"
" p = &x;\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (warning) Address of local variable x is assigned to global pointer p and not reassigned before x goes out of scope.\n", errout.str());
check("int *p;\n"
"void f() {\n"
" int x;\n"
" p = &x;\n"
" p = 0;\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void returnLocalVariable1() { void returnLocalVariable1() {
check("char *foo()\n" check("char *foo()\n"
"{\n" "{\n"