Fixed #8325 (False negative: address of auto variable being returned when assigned to another variable first)

This commit is contained in:
Daniel Marjamäki 2018-01-27 14:48:45 +01:00
parent 27d9aaa8f5
commit c110770481
4 changed files with 36 additions and 0 deletions

View File

@ -279,6 +279,26 @@ void CheckAutoVariables::autoVariables()
errorAutoVariableAssignment(tok->next(), false);
}
// Critical return
else if (Token::Match(tok, "return %var% ;") && isAutoVar(tok->next())) {
const std::list<ValueFlow::Value> &values = tok->next()->values();
const ValueFlow::Value *value = nullptr;
for (std::list<ValueFlow::Value>::const_iterator it = values.begin(); it != values.end(); ++it) {
if (!it->isTokValue())
continue;
if (!_settings->inconclusive && it->isInconclusive())
continue;
if (!Token::Match(it->tokvalue->previous(), "= & %var%"))
continue;
if (!isAutoVar(it->tokvalue->next()))
continue;
if (!value || value->isInconclusive())
value = &(*it);
}
if (value)
errorReturnAddressToAutoVariable(tok, value);
}
else if (Token::Match(tok, "return & %var% ;")) {
const Token* varTok = tok->tokAt(2);
if (isAutoVar(varTok))
@ -336,6 +356,11 @@ void CheckAutoVariables::errorReturnAddressToAutoVariable(const Token *tok)
reportError(tok, Severity::error, "returnAddressOfAutoVariable", "Address of an auto-variable returned.", CWE562, false);
}
void CheckAutoVariables::errorReturnAddressToAutoVariable(const Token *tok, const ValueFlow::Value *value)
{
reportError(tok, Severity::error, "returnAddressOfAutoVariable", "Address of auto-variable '" + value->tokvalue->astOperand1()->expressionString() + "' returned", CWE562, false);
}
void CheckAutoVariables::errorReturnPointerToLocalArray(const Token *tok)
{
reportError(tok, Severity::error, "returnLocalVariable", "Pointer to local array variable returned.", CWE562, false);

View File

@ -82,6 +82,7 @@ private:
static bool returnTemporary(const Token *tok);
void errorReturnAddressToAutoVariable(const Token *tok);
void errorReturnAddressToAutoVariable(const Token *tok, const ValueFlow::Value *value);
void errorAssignAddressOfLocalArrayToGlobalPointer(const Token *pointer, const Token *array);
void errorAssignAddressOfLocalVariableToGlobalPointer(const Token *pointer, const Token *variable);
void errorReturnPointerToLocalArray(const Token *tok);

View File

@ -7035,6 +7035,7 @@ bool Tokenizer::simplifyKnownVariablesSimplify(Token **tok2, Token *tok3, unsign
// return variable..
if (Token::Match(tok3, "return %varid% %any%", varid) &&
valueToken->str() != "&" &&
(tok3->tokAt(2)->isExtendedOp() || tok3->strAt(2) == ";") &&
value[0] != '\"') {
tok3->next()->str(value);

View File

@ -95,6 +95,7 @@ private:
TEST_CASE(returnLocalVariable3); // &x[0]
TEST_CASE(returnLocalVariable4); // x+y
TEST_CASE(returnLocalVariable5); // cast
TEST_CASE(returnLocalVariable6); // valueflow
// return reference..
TEST_CASE(returnReference1);
@ -755,6 +756,14 @@ private:
ASSERT_EQUALS("[test.cpp:3]: (error) Pointer to local array variable returned.\n", errout.str());
}
void returnLocalVariable6() { // valueflow
check("int *foo() {\n"
" int x = 123;\n"
" int p = &x;\n"
" return p;\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (error) Address of auto-variable 'x' returned\n", errout.str());
}
void returnReference1() {
check("std::string &foo()\n"