Skip to content

Commit 843f95e

Browse files
Fix #14005 FP: returnDanglingLifetime while returning reference to struct field (danmar#7661)
Co-authored-by: chrchr-github <[email protected]>
1 parent 8244dfa commit 843f95e

File tree

2 files changed

+29
-0
lines changed

2 files changed

+29
-0
lines changed

lib/valueflow.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3166,6 +3166,14 @@ static void valueFlowLifetime(TokenList &tokenlist, ErrorLogger &errorLogger, co
31663166
else if (tok->isUnaryOp("&")) {
31673167
if (Token::simpleMatch(tok->astParent(), "*"))
31683168
continue;
3169+
if (Token::simpleMatch(tok->astOperand1(), "[")) {
3170+
const Token* const op1 = tok->astOperand1()->astOperand1();
3171+
const Token* tok2 = op1;
3172+
while (Token::simpleMatch(tok2, "."))
3173+
tok2 = tok2->astOperand2();
3174+
if (tok2 && tok2 != op1 && (!tok2->variable() || !tok2->variable()->isArray()) && !(tok2->valueType() && tok2->valueType()->container))
3175+
continue;
3176+
}
31693177
for (const ValueFlow::LifetimeToken& lt : ValueFlow::getLifetimeTokens(tok->astOperand1(), settings)) {
31703178
if (!settings.certainty.isEnabled(Certainty::inconclusive) && lt.inconclusive)
31713179
continue;

test/testautovariables.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ class TestAutoVariables : public TestFixture {
7878
TEST_CASE(testautovar_return3);
7979
TEST_CASE(testautovar_return4);
8080
TEST_CASE(testautovar_return5);
81+
TEST_CASE(testautovar_return6);
8182
TEST_CASE(testautovar_extern);
8283
TEST_CASE(testautovar_reassigned);
8384
TEST_CASE(testinvaliddealloc);
@@ -624,6 +625,26 @@ class TestAutoVariables : public TestFixture {
624625
ASSERT_EQUALS("", errout_str());
625626
}
626627

628+
void testautovar_return6() { // #14005
629+
check("struct S;\n"
630+
"struct T { const struct S *s; };\n"
631+
"extern struct T factory();\n"
632+
"const struct S* f() {\n"
633+
" struct T t = factory();\n"
634+
" return &t.s[0];\n"
635+
"}\n");
636+
ASSERT_EQUALS("", errout_str());
637+
638+
check("struct S;\n"
639+
"struct T { std::vector<struct S> v; };\n"
640+
"extern struct T factory();\n"
641+
"const struct S* f() {\n"
642+
" struct T t = factory();\n"
643+
" return &t.v[0];\n"
644+
"}\n");
645+
ASSERT_EQUALS("[test.cpp:6:12] -> [test.cpp:5:14] -> [test.cpp:6:12]: (error) Returning pointer to local variable 't' that will be invalid when returning. [returnDanglingLifetime]\n", errout_str());
646+
}
647+
627648
void testautovar_extern() {
628649
check("struct foo *f()\n"
629650
"{\n"

0 commit comments

Comments
 (0)