Auto variables: Assign address of local variable to global pointer (#6825)
This commit is contained in:
parent
9109956c8c
commit
cb297a00fc
|
@ -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",
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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"
|
||||||
|
|
Loading…
Reference in New Issue