Fixed #4641 (False positive: Address of local auto-variable assigned to a function parameter)
This commit is contained in:
parent
876e9c0039
commit
cd5e32446f
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue