Skip to content

Commit 7b481f4

Browse files
Fix #11168 FP returnDanglingLifetime (local iterator points at global struct) (cppcheck-opensource#8979)
Co-authored-by: chrchr-github <noreply@github.com>
1 parent bf89a6f commit 7b481f4

2 files changed

Lines changed: 31 additions & 2 deletions

File tree

‎lib/valueflow.cpp‎

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1473,6 +1473,19 @@ ValueFlow::Value ValueFlow::getLifetimeObjValue(const Token *tok, bool inconclus
14731473
return std::move(values.front());
14741474
}
14751475

1476+
static bool checkDotLifetime(const Token* dot, const Token* tok)
1477+
{
1478+
if (Token::simpleMatch(dot->astOperand1(), "."))
1479+
return false;
1480+
if (!dot->astOperand2())
1481+
return true;
1482+
if (dot->astOperand2()->varId() && tok->isUnaryOp("*"))
1483+
return dot->astOperand2()->variable() && dot->astOperand2()->variable()->isArray();
1484+
if (dot->astOperand2()->valueType() && dot->astOperand2()->valueType()->reference != Reference::None)
1485+
return false;
1486+
return true;
1487+
}
1488+
14761489
template<class Predicate>
14771490
static std::vector<ValueFlow::LifetimeToken> getLifetimeTokens(const Token* tok,
14781491
bool escape,
@@ -1585,8 +1598,7 @@ static std::vector<ValueFlow::LifetimeToken> getLifetimeTokens(const Token* tok,
15851598
if (vartok->str() == "[" || vartok->isUnaryOp("*"))
15861599
vartok = vartok->astOperand1();
15871600
else if (vartok->str() == ".") {
1588-
if (!Token::simpleMatch(vartok->astOperand1(), ".") &&
1589-
!(vartok->astOperand2() && vartok->astOperand2()->valueType() && vartok->astOperand2()->valueType()->reference != Reference::None))
1601+
if (checkDotLifetime(vartok, tok))
15901602
vartok = vartok->astOperand1();
15911603
else
15921604
break;

‎test/testautovariables.cpp‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4581,6 +4581,23 @@ class TestAutoVariables : public TestFixture {
45814581
ASSERT_EQUALS("[test.cpp:5:11] -> [test.cpp:4:9] -> [test.cpp:5:6]: (error) Non-local variable 'g.a' will use pointer to local variable 'x'. [danglingLifetime]\n"
45824582
"[test.cpp:5:11] -> [test.cpp:4:9] -> [test.cpp:6:13]: (error) Returning pointer to local variable 'x' that will be invalid when returning. [returnDanglingLifetime]\n",
45834583
errout_str());
4584+
4585+
check("int* f() {\n" // #11168
4586+
" auto x = get();\n"
4587+
" return &*x.a;\n"
4588+
"}\n");
4589+
ASSERT_EQUALS("", errout_str());
4590+
4591+
check("struct S { int a[1]; };\n"
4592+
"int& f(S s) {\n"
4593+
" return *s.a;\n"
4594+
"}\n"
4595+
"int* g(S s) {\n"
4596+
" return &*s.a;\n"
4597+
"}\n");
4598+
ASSERT_EQUALS("[test.cpp:3:12]: (error) Reference to local variable returned. [returnReference]\n"
4599+
"[test.cpp:6:12] -> [test.cpp:5:10] -> [test.cpp:6:12]: (error) Returning pointer to local variable 's' that will be invalid when returning. [returnDanglingLifetime]\n",
4600+
errout_str());
45844601
}
45854602

45864603
void danglingLifetimeClassMemberFunctions()

0 commit comments

Comments
 (0)