Fixed #8325 (False negative: address of auto variable being returned when assigned to another variable first)
This commit is contained in:
parent
27d9aaa8f5
commit
c110770481
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue