From f42648fe2262170d065d1cc0e5e5b8a487c99435 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sat, 1 Dec 2018 10:11:02 +0100 Subject: [PATCH] Fixed #8114 (false positive: Address of local auto-variable assigned to a function parameter.) --- lib/checkautovariables.cpp | 33 ++++++++++++++++++++++++++++++--- test/testautovariables.cpp | 9 +++++++++ 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/lib/checkautovariables.cpp b/lib/checkautovariables.cpp index e95b8689a..675781635 100644 --- a/lib/checkautovariables.cpp +++ b/lib/checkautovariables.cpp @@ -167,6 +167,34 @@ static bool checkRvalueExpression(const Token * const vartok) return ((next->str() != "." || (!var->isPointer() && (!var->isClass() || var->type()))) && next->strAt(2) != "."); } +static bool isAddressOfLocalVariableRecursive(const Token *expr) +{ + if (!expr) + return false; + if (Token::Match(expr, "+|-")) + return isAddressOfLocalVariableRecursive(expr->astOperand1()) || isAddressOfLocalVariableRecursive(expr->astOperand2()); + if (expr->str() == "(" && !expr->astOperand2()) + return isAddressOfLocalVariableRecursive(expr->astOperand1()); + if (expr->str() == "&" && !expr->astOperand2()) { + const Token *op = expr->astOperand1(); + bool deref = false; + while (Token::Match(op, ".|[")) { + if (op->str() == "[") + deref = true; + op = op->astOperand1(); + } + return op && isAutoVar(op) && (!deref || !op->variable()->isPointer()); + } + return false; +} + +static bool isAddressOfLocalVariable(const Token *expr) +{ + if (!expr || !expr->valueType() || expr->valueType()->pointer == 0) + return false; + return isAddressOfLocalVariableRecursive(expr); +} + static bool variableIsUsedInScope(const Token* start, unsigned int varId, const Scope *scope) { if (!start) // Ticket #5024 @@ -239,9 +267,8 @@ void CheckAutoVariables::autoVariables() if (Token::Match(tok, "[;{}] %var% = & %var%") && isRefPtrArg(tok->next()) && isAutoVar(tok->tokAt(4))) { if (checkRvalueExpression(tok->tokAt(4))) errorAutoVariableAssignment(tok->next(), false); - } else if (Token::Match(tok, "[;{}] * %var% = & %var%") && isPtrArg(tok->tokAt(2)) && isAutoVar(tok->tokAt(5))) { - if (checkRvalueExpression(tok->tokAt(5))) - errorAutoVariableAssignment(tok->next(), false); + } else if (Token::Match(tok, "[;{}] * %var% =") && isPtrArg(tok->tokAt(2)) && isAddressOfLocalVariable(tok->tokAt(3)->astOperand2())) { + errorAutoVariableAssignment(tok->next(), false); } else if (mSettings->isEnabled(Settings::WARNING) && Token::Match(tok, "[;{}] %var% = &| %var% ;") && isGlobalPtr(tok->next())) { const Token * const pointer = tok->next(); if (isAutoVarArray(tok->tokAt(3))) { diff --git a/test/testautovariables.cpp b/test/testautovariables.cpp index a2d834137..e717596aa 100644 --- a/test/testautovariables.cpp +++ b/test/testautovariables.cpp @@ -75,6 +75,7 @@ private: TEST_CASE(testautovar13); // ticket #5537 - crash TEST_CASE(testautovar14); // ticket #4776 - assignment of function parameter, goto TEST_CASE(testautovar15); // ticket #6538 + TEST_CASE(testautovar16); // ticket #8114 TEST_CASE(testautovar_array1); TEST_CASE(testautovar_array2); TEST_CASE(testautovar_ptrptr); // ticket #6956 @@ -439,6 +440,14 @@ private: ASSERT_EQUALS("", errout.str()); } + void testautovar16() { // Ticket #8114 + check("void f(const void* ptr, bool* result) {\n" + " int dummy;\n" + " *result = (&dummy < ptr);\n" + "}"); + ASSERT_EQUALS("", errout.str()); + } + void testautovar_array1() { check("void func1(int* arr[2])\n" "{\n"