Fix #11732 FN autoVariables with array and std::string (#5096)

* Fix #11732 FP autoVariables when reassigning argv

* Fix #11732 FN autoVariables with array and std::string

* Add test

* Format

* Format
This commit is contained in:
chrchr-github 2023-05-31 20:55:55 +02:00 committed by GitHub
parent 0b44429a7c
commit 238cf75f6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 41 additions and 1 deletions

View File

@ -143,6 +143,29 @@ static bool isAutoVarArray(const Token *tok)
return false;
}
static bool isLocalContainerBuffer(const Token* tok)
{
if (!tok)
return false;
// x+y
if (tok->str() == "+")
return isLocalContainerBuffer(tok->astOperand1()) || isLocalContainerBuffer(tok->astOperand2());
if (tok->str() != "(" || !Token::simpleMatch(tok->astOperand1(), "."))
return false;
tok = tok->astOperand1()->astOperand1();
const Variable* var = tok->variable();
if (!var || !var->isLocal() || var->isStatic())
return false;
const Library::Container::Yield yield = astContainerYield(tok);
return yield == Library::Container::Yield::BUFFER || yield == Library::Container::Yield::BUFFER_NT;
}
// Verification that we really take the address of a local variable
static bool checkRvalueExpression(const Token * const vartok)
{
@ -232,6 +255,10 @@ void CheckAutoVariables::assignFunctionArg()
}
}
static bool isAutoVariableRHS(const Token* tok) {
return isAddressOfLocalVariable(tok) || isAutoVarArray(tok) || isLocalContainerBuffer(tok);
}
void CheckAutoVariables::autoVariables()
{
const bool printInconclusive = mSettings->certainty.isEnabled(Certainty::inconclusive);
@ -266,7 +293,8 @@ void CheckAutoVariables::autoVariables()
}
tok = tok->tokAt(4);
} else if (Token::Match(tok, "[;{}] %var% [") && Token::simpleMatch(tok->linkAt(2), "] =") &&
(isPtrArg(tok->next()) || isArrayArg(tok->next(), mSettings)) && isAddressOfLocalVariable(tok->linkAt(2)->next()->astOperand2())) {
(isPtrArg(tok->next()) || isArrayArg(tok->next(), mSettings)) &&
isAutoVariableRHS(tok->linkAt(2)->next()->astOperand2())) {
errorAutoVariableAssignment(tok->next(), false);
}
// Invalid pointer deallocation

View File

@ -524,6 +524,18 @@ private:
" argv[0] = &a[0];\n"
"}\n");
ASSERT_EQUALS("", errout.str());
check("void f(char* c[]) {\n"
" char a[] = \"abc\";\n"
" c[0] = a;\n"
"}\n"
"void g(char* c[]) {\n"
" std::string a = \"abc\";\n"
" c[0] = a.data();\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3]: (error) Address of local auto-variable assigned to a function parameter.\n"
"[test.cpp:7]: (error) Address of local auto-variable assigned to a function parameter.\n",
errout.str());
}
void testautovar_normal() {