Fixed #4641 (False positive: Address of local auto-variable assigned to a function parameter)

This commit is contained in:
Daniel Marjamäki 2013-06-13 16:19:19 +02:00
parent 876e9c0039
commit cd5e32446f
2 changed files with 39 additions and 9 deletions

View File

@ -82,8 +82,20 @@ bool CheckAutoVariables::isAutoVarArray(const Token *tok)
}
// Verification that we really take the address of a local variable
static bool checkRvalueExpression(const Variable* var, const Token* next)
static bool checkRvalueExpression(const Token * const vartok)
{
const Variable * const var = vartok->variable();
if (var == NULL)
return false;
const Token * const next = vartok->next();
// &a.b[0]
if (Token::Match(vartok, "%var% . %var% [") && !var->isPointer()) {
const Variable *var2 = next->next()->variable();
return var2 && !var2->isPointer();
}
return((next->str() != "." || (!var->isPointer() && (!var->isClass() || var->type()))) && next->strAt(2) != ".");
}
@ -112,12 +124,10 @@ void CheckAutoVariables::autoVariables()
for (const Token *tok = scope->classStart; tok && tok != scope->classEnd; tok = tok->next()) {
// Critical assignment
if (Token::Match(tok, "[;{}] %var% = & %var%") && isRefPtrArg(tok->next()) && isAutoVar(tok->tokAt(4))) {
const Variable * var = tok->tokAt(4)->variable();
if (checkRvalueExpression(var, tok->tokAt(5)))
if (checkRvalueExpression(tok->tokAt(4)))
errorAutoVariableAssignment(tok->next(), false);
} else if (Token::Match(tok, "[;{}] * %var% = & %var%") && isPtrArg(tok->tokAt(2)) && isAutoVar(tok->tokAt(5))) {
const Variable * var = tok->tokAt(5)->variable();
if (checkRvalueExpression(var, tok->tokAt(6)))
if (checkRvalueExpression(tok->tokAt(5)))
errorAutoVariableAssignment(tok->next(), false);
} else if (reportWarnings &&
Token::Match(tok, "[;{}] %var% =") &&
@ -129,8 +139,8 @@ void CheckAutoVariables::autoVariables()
if (_settings->inconclusive) {
const Variable * var1 = tok->next()->variable();
if (var1 && var1->isArgument() && var1->isPointer()) {
const Variable * var2 = tok->tokAt(6)->variable();
if (isAutoVar(tok->tokAt(6)) && checkRvalueExpression(var2, tok->tokAt(7)))
const Token * const var2tok = tok->tokAt(6);
if (isAutoVar(var2tok) && checkRvalueExpression(var2tok))
errorAutoVariableAssignment(tok->next(), true);
}
}
@ -154,8 +164,7 @@ void CheckAutoVariables::autoVariables()
tok = tok->tokAt(4);
} else if (Token::Match(tok, "[;{}] %var% [") && Token::Match(tok->linkAt(2), "] = & %var%") && isPtrArg(tok->next()) && isAutoVar(tok->linkAt(2)->tokAt(3))) {
const Token* const varTok = tok->linkAt(2)->tokAt(3);
const Variable * var = varTok->variable();
if (checkRvalueExpression(var, varTok->next()))
if (checkRvalueExpression(varTok))
errorAutoVariableAssignment(tok->next(), false);
}
// Critical return

View File

@ -77,6 +77,7 @@ private:
TEST_CASE(testautovar8);
TEST_CASE(testautovar9);
TEST_CASE(testautovar10); // ticket #2930 - void f(char *p) { p = '\0'; }
TEST_CASE(testautovar11); // ticket #4641 - fp, assign local struct member address to function parameter
TEST_CASE(testautovar_array1);
TEST_CASE(testautovar_array2);
TEST_CASE(testautovar_return1);
@ -305,6 +306,26 @@ private:
ASSERT_EQUALS("", errout.str());
}
void testautovar11() { // #4641 - fp, assign local struct member address to function parameter
check("struct A {\n"
" char *data[10];\n"
"};\n"
"void foo(char** p) {\n"
" struct A a = bar();\n"
" *p = &a.data[0];\n"
"}");
ASSERT_EQUALS("", errout.str());
check("struct A {\n"
" char data[10];\n"
"};\n"
"void foo(char** p) {\n"
" struct A a = bar();\n"
" *p = &a.data[0];\n"
"}");
ASSERT_EQUALS("[test.cpp:6]: (error) Address of local auto-variable assigned to a function parameter.\n", errout.str());
}
void testautovar_array1() {
check("void func1(int* arr[2])\n"
"{\n"