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);
|
errorAutoVariableAssignment(tok->next(), false);
|
||||||
}
|
}
|
||||||
// Critical return
|
// 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% ;")) {
|
else if (Token::Match(tok, "return & %var% ;")) {
|
||||||
const Token* varTok = tok->tokAt(2);
|
const Token* varTok = tok->tokAt(2);
|
||||||
if (isAutoVar(varTok))
|
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);
|
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)
|
void CheckAutoVariables::errorReturnPointerToLocalArray(const Token *tok)
|
||||||
{
|
{
|
||||||
reportError(tok, Severity::error, "returnLocalVariable", "Pointer to local array variable returned.", CWE562, false);
|
reportError(tok, Severity::error, "returnLocalVariable", "Pointer to local array variable returned.", CWE562, false);
|
||||||
|
|
|
@ -82,6 +82,7 @@ private:
|
||||||
static bool returnTemporary(const Token *tok);
|
static bool returnTemporary(const Token *tok);
|
||||||
|
|
||||||
void errorReturnAddressToAutoVariable(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 errorAssignAddressOfLocalArrayToGlobalPointer(const Token *pointer, const Token *array);
|
||||||
void errorAssignAddressOfLocalVariableToGlobalPointer(const Token *pointer, const Token *variable);
|
void errorAssignAddressOfLocalVariableToGlobalPointer(const Token *pointer, const Token *variable);
|
||||||
void errorReturnPointerToLocalArray(const Token *tok);
|
void errorReturnPointerToLocalArray(const Token *tok);
|
||||||
|
|
|
@ -7035,6 +7035,7 @@ bool Tokenizer::simplifyKnownVariablesSimplify(Token **tok2, Token *tok3, unsign
|
||||||
|
|
||||||
// return variable..
|
// return variable..
|
||||||
if (Token::Match(tok3, "return %varid% %any%", varid) &&
|
if (Token::Match(tok3, "return %varid% %any%", varid) &&
|
||||||
|
valueToken->str() != "&" &&
|
||||||
(tok3->tokAt(2)->isExtendedOp() || tok3->strAt(2) == ";") &&
|
(tok3->tokAt(2)->isExtendedOp() || tok3->strAt(2) == ";") &&
|
||||||
value[0] != '\"') {
|
value[0] != '\"') {
|
||||||
tok3->next()->str(value);
|
tok3->next()->str(value);
|
||||||
|
|
|
@ -95,6 +95,7 @@ private:
|
||||||
TEST_CASE(returnLocalVariable3); // &x[0]
|
TEST_CASE(returnLocalVariable3); // &x[0]
|
||||||
TEST_CASE(returnLocalVariable4); // x+y
|
TEST_CASE(returnLocalVariable4); // x+y
|
||||||
TEST_CASE(returnLocalVariable5); // cast
|
TEST_CASE(returnLocalVariable5); // cast
|
||||||
|
TEST_CASE(returnLocalVariable6); // valueflow
|
||||||
|
|
||||||
// return reference..
|
// return reference..
|
||||||
TEST_CASE(returnReference1);
|
TEST_CASE(returnReference1);
|
||||||
|
@ -755,6 +756,14 @@ private:
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (error) Pointer to local array variable returned.\n", errout.str());
|
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() {
|
void returnReference1() {
|
||||||
check("std::string &foo()\n"
|
check("std::string &foo()\n"
|
||||||
|
|
Loading…
Reference in New Issue