diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index aa77d16e1f7..b4f90fe2f36 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -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()) && !(tok2->valueType() && tok2->valueType()->container)) + 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..453fadfaf50 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,26 @@ class TestAutoVariables : public TestFixture { ASSERT_EQUALS("", errout_str()); } + void testautovar_return6() { // #14005 + check("struct S;\n" + "struct T { 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()); + + 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() { check("struct foo *f()\n" "{\n"