diff --git a/lib/checkautovariables.cpp b/lib/checkautovariables.cpp index 1f261a611..878bc57b7 100644 --- a/lib/checkautovariables.cpp +++ b/lib/checkautovariables.cpp @@ -165,6 +165,12 @@ void CheckAutoVariables::autoVariables() { errorReturnAddressToAutoVariable(tok); } + else if (Token::Match(tok, "return & %var% ;") && tok->tokAt(2)->varId()) + { + const Variable * var1 = symbolDatabase->getVariableFromVarId(tok->tokAt(2)->varId()); + if (var1 && var1->isArgument() && var1->typeStartToken() == var1->typeEndToken()) + errorReturnAddressOfFunctionParameter(tok, tok->strAt(2)); + } // Invalid pointer deallocation else if (Token::Match(tok, "free ( %var% ) ;") && isAutoVarArray(tok->tokAt(2)->varId())) { @@ -264,6 +270,12 @@ void CheckAutoVariables::errorAutoVariableAssignment(const Token *tok, bool inco } } +void CheckAutoVariables::errorReturnAddressOfFunctionParameter(const Token *tok, const std::string &varname) +{ + reportError(tok, Severity::error, "returnAddressOfFunctionParameter", + "Return the address of function parameter '" + varname + "'"); +} + //--------------------------------------------------------------------------- // return temporary? diff --git a/lib/checkautovariables.h b/lib/checkautovariables.h index 7f77150b2..bddfb4bc3 100644 --- a/lib/checkautovariables.h +++ b/lib/checkautovariables.h @@ -89,6 +89,7 @@ private: void errorReturnAutocstr(const Token *tok); void errorReturnTempPointer(const Token *tok); void errorInvalidDeallocation(const Token *tok); + void errorReturnAddressOfFunctionParameter(const Token *tok, const std::string &varname); void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) { @@ -101,6 +102,7 @@ private: c.errorReturnAutocstr(0); c.errorReturnTempPointer(0); c.errorInvalidDeallocation(0); + c.errorReturnAddressOfFunctionParameter(0, "parameter"); } std::string myName() const @@ -114,7 +116,8 @@ private: "Check:\n" "* returning a pointer to auto or temporary variable\n" "* assigning address of an variable to an effective parameter of a function\n" - "* returning reference to local/temporary variable\n"; + "* returning reference to local/temporary variable\n" + "* returning address of function parameter\n"; } }; /// @} diff --git a/test/testautovariables.cpp b/test/testautovariables.cpp index 54feb030d..f1a5ef264 100644 --- a/test/testautovariables.cpp +++ b/test/testautovariables.cpp @@ -98,6 +98,8 @@ private: // global namespace TEST_CASE(testglobalnamespace); + + TEST_CASE(returnParameterAddress); } @@ -564,6 +566,16 @@ private: ASSERT_EQUALS("", errout.str()); } + void returnParameterAddress() + { + check("int* foo(int y)\n" + "{\n" + " return &y;\n" + "}\n"); + + ASSERT_EQUALS("[test.cpp:3]: (error) Return the address of function parameter 'y'\n", errout.str()); + } + }; REGISTER_TEST(TestAutoVariables)