From e1a4a1852841422df723d2f96ee9c9ee322abc74 Mon Sep 17 00:00:00 2001 From: Paul Fultz II Date: Tue, 21 Mar 2023 17:18:01 -0500 Subject: [PATCH] Fix 11609: False positive: Returning iterator to local container 'k' that will be invalid when returning where 'k' is an iterator. (#4907) --- lib/valueflow.cpp | 10 ++++++---- test/testautovariables.cpp | 10 ++++++++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 43dd2f97e..04458d84a 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -4824,12 +4824,14 @@ static void valueFlowLifetime(TokenList *tokenlist, SymbolDatabase* /*db*/, Erro if (astIsIterator(parent->tokAt(2))) { master.errorPath.emplace_back(parent->tokAt(2), "Iterator to container is created here."); master.lifetimeKind = ValueFlow::Value::LifetimeKind::Iterator; - } else if (astIsIterator(parent)) { + } else if (astIsIterator(parent) && Token::Match(parent->previous(), "%name% (") && + contains({Library::Container::Yield::START_ITERATOR, Library::Container::Yield::END_ITERATOR}, + astFunctionYield(parent->previous(), settings))) { master.errorPath.emplace_back(parent, "Iterator to container is created here."); master.lifetimeKind = ValueFlow::Value::LifetimeKind::Iterator; - } - else if ((astIsPointer(parent->tokAt(2)) && !isContainerOfPointers(tok->valueType()->containerTypeToken, settings)) || - Token::Match(parent->next(), "data|c_str")) { + } else if ((astIsPointer(parent->tokAt(2)) && + !isContainerOfPointers(tok->valueType()->containerTypeToken, settings)) || + Token::Match(parent->next(), "data|c_str")) { master.errorPath.emplace_back(parent->tokAt(2), "Pointer to container is created here."); master.lifetimeKind = ValueFlow::Value::LifetimeKind::Object; } else { diff --git a/test/testautovariables.cpp b/test/testautovariables.cpp index 3c0de6d21..ef71b0c91 100644 --- a/test/testautovariables.cpp +++ b/test/testautovariables.cpp @@ -3891,6 +3891,16 @@ private: " }\n" "}\n"); ASSERT_EQUALS("", errout.str()); + + // #11609 + check("struct S {\n" + " void f(const std::string& s) {\n" + " auto it = m.find(s.substr(1,4));\n" + " if (it == m.end()) {}\n" + " }\n" + " std::map m;\n" + "};\n"); + ASSERT_EQUALS("", errout.str()); } void danglingLifetimeBorrowedMembers()