From 9778fd22cba8bbf0af5c82069733907a5c2f8185 Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Thu, 10 Jul 2025 22:13:35 +0200 Subject: [PATCH 1/4] Fix #14005 FP: returnDanglingLifetime while returning reference to struct field --- lib/valueflow.cpp | 10 +++++++++- test/testautovariables.cpp | 12 ++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index aa77d16e1f7..e797610a469 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - +#include /** * @brief This is the ValueFlow component in Cppcheck. * @@ -3119,6 +3119,14 @@ static void valueFlowLifetime(TokenList &tokenlist, ErrorLogger &errorLogger, co else if (tok->isUnaryOp("&")) { if (Token::simpleMatch(tok->astParent(), "*")) continue; + if (Token::simpleMatch(tok->astOperand1(), "[")) { + const Token* const op1 = tok->astOperand1()->astOperand1(); + const Token* tok2 = op1; + while (Token::simpleMatch(tok2, ".")) + tok2 = tok2->astOperand2(); + if (tok2 && tok2 != op1 && (!tok2->variable() || !tok2->variable()->isArray())) + continue; + } for (const ValueFlow::LifetimeToken& lt : ValueFlow::getLifetimeTokens(tok->astOperand1(), settings)) { if (!settings.certainty.isEnabled(Certainty::inconclusive) && lt.inconclusive) continue; diff --git a/test/testautovariables.cpp b/test/testautovariables.cpp index 6785976a3d2..10eb7b71901 100644 --- a/test/testautovariables.cpp +++ b/test/testautovariables.cpp @@ -78,6 +78,7 @@ class TestAutoVariables : public TestFixture { TEST_CASE(testautovar_return3); TEST_CASE(testautovar_return4); TEST_CASE(testautovar_return5); + TEST_CASE(testautovar_return6); TEST_CASE(testautovar_extern); TEST_CASE(testautovar_reassigned); TEST_CASE(testinvaliddealloc); @@ -624,6 +625,17 @@ class TestAutoVariables : public TestFixture { ASSERT_EQUALS("", errout_str()); } + void testautovar_return6() { // #14005 + check("struct S;\n" + "struct S { const struct S *s; };\n" + "extern struct T factory();\n" + "const struct S* f() {\n" + " struct T t = factory();\n" + " return &t.s[0];\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); + } + void testautovar_extern() { check("struct foo *f()\n" "{\n" From ece8678396186754f5f520a3bf14374b01a8f7d8 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Thu, 10 Jul 2025 22:15:01 +0200 Subject: [PATCH 2/4] Update valueflow.cpp --- lib/valueflow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index e797610a469..f7655742730 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#include + /** * @brief This is the ValueFlow component in Cppcheck. * From 8df5f3b44e14a8f8101b1c612cc3974b865d81f8 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Fri, 11 Jul 2025 08:10:23 +0200 Subject: [PATCH 3/4] Update testautovariables.cpp --- test/testautovariables.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/testautovariables.cpp b/test/testautovariables.cpp index 10eb7b71901..3f264fca146 100644 --- a/test/testautovariables.cpp +++ b/test/testautovariables.cpp @@ -627,7 +627,7 @@ class TestAutoVariables : public TestFixture { void testautovar_return6() { // #14005 check("struct S;\n" - "struct S { const struct S *s; };\n" + "struct T { const struct S *s; };\n" "extern struct T factory();\n" "const struct S* f() {\n" " struct T t = factory();\n" From e412c1ffccd8e8f6ede695d40d1ca5e4f9f8aee8 Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Sat, 12 Jul 2025 01:44:36 +0200 Subject: [PATCH 4/4] Fix FN --- lib/valueflow.cpp | 2 +- test/testautovariables.cpp | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index f7655742730..b4f90fe2f36 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -3124,7 +3124,7 @@ static void valueFlowLifetime(TokenList &tokenlist, ErrorLogger &errorLogger, co const Token* tok2 = op1; while (Token::simpleMatch(tok2, ".")) tok2 = tok2->astOperand2(); - if (tok2 && tok2 != op1 && (!tok2->variable() || !tok2->variable()->isArray())) + if (tok2 && tok2 != op1 && (!tok2->variable() || !tok2->variable()->isArray()) && !(tok2->valueType() && tok2->valueType()->container)) continue; } for (const ValueFlow::LifetimeToken& lt : ValueFlow::getLifetimeTokens(tok->astOperand1(), settings)) { diff --git a/test/testautovariables.cpp b/test/testautovariables.cpp index 3f264fca146..453fadfaf50 100644 --- a/test/testautovariables.cpp +++ b/test/testautovariables.cpp @@ -634,6 +634,15 @@ class TestAutoVariables : public TestFixture { " return &t.s[0];\n" "}\n"); ASSERT_EQUALS("", errout_str()); + + check("struct S;\n" + "struct T { std::vector v; };\n" + "extern struct T factory();\n" + "const struct S* f() {\n" + " struct T t = factory();\n" + " return &t.v[0];\n" + "}\n"); + 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()); } void testautovar_extern() {