From 238cf75f6fd96cde52723c29171c112468ccd13d Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Wed, 31 May 2023 20:55:55 +0200 Subject: [PATCH] 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 --- lib/checkautovariables.cpp | 30 +++++++++++++++++++++++++++++- test/testautovariables.cpp | 12 ++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/lib/checkautovariables.cpp b/lib/checkautovariables.cpp index 5fa916932..8a280d0cd 100644 --- a/lib/checkautovariables.cpp +++ b/lib/checkautovariables.cpp @@ -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 diff --git a/test/testautovariables.cpp b/test/testautovariables.cpp index 427d07474..a05fca0c5 100644 --- a/test/testautovariables.cpp +++ b/test/testautovariables.cpp @@ -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() {