Merge pull request #2710 from pfultz2/fp-invalid-container-pointer

Fix issue 9796: False positive: lifetime, pointer item is not deallocated by pop_back
This commit is contained in:
Daniel Marjamäki 2020-07-22 09:24:54 +02:00 committed by GitHub
commit 2fd44fa464
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 42 additions and 1 deletions

View File

@ -3623,11 +3623,18 @@ static void valueFlowLifetime(TokenList *tokenlist, SymbolDatabase*, ErrorLogger
if (!Token::Match(parent, ". %name% (")) if (!Token::Match(parent, ". %name% ("))
continue; continue;
bool isContainerOfPointers = true;
const Token* containerTypeToken = tok->valueType()->containerTypeToken;
if (containerTypeToken) {
ValueType vt = ValueType::parseDecl(containerTypeToken, settings);
isContainerOfPointers = vt.pointer > 0;
}
LifetimeStore ls; LifetimeStore ls;
if (astIsIterator(parent->tokAt(2))) if (astIsIterator(parent->tokAt(2)))
ls = LifetimeStore{tok, "Iterator to container is created here.", ValueFlow::Value::LifetimeKind::Iterator}; ls = LifetimeStore{tok, "Iterator to container is created here.", ValueFlow::Value::LifetimeKind::Iterator};
else if (astIsPointer(parent->tokAt(2)) || Token::Match(parent->next(), "data|c_str")) else if ((astIsPointer(parent->tokAt(2)) && !isContainerOfPointers) || Token::Match(parent->next(), "data|c_str"))
ls = LifetimeStore{tok, "Pointer to container is created here.", ValueFlow::Value::LifetimeKind::Object}; ls = LifetimeStore{tok, "Pointer to container is created here.", ValueFlow::Value::LifetimeKind::Object};
else else
continue; continue;

View File

@ -4164,6 +4164,40 @@ private:
" v.push_back(\"y\");\n" " v.push_back(\"y\");\n"
"}\n",true); "}\n",true);
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
// #9796
check("struct A {};\n"
"void f() {\n"
" std::vector<A *> v;\n"
" A *a = new A();\n"
" v.push_back(a);\n"
" A *b = v.back();\n"
" v.pop_back();\n"
" delete b;\n"
"}\n" ,true);
ASSERT_EQUALS("", errout.str());
check("struct A {};\n"
"void f() {\n"
" std::vector<A *, std::allocator<A*>> v;\n"
" A *a = new A();\n"
" v.push_back(a);\n"
" A *b = v.back();\n"
" v.pop_back();\n"
" delete b;\n"
"}\n" ,true);
ASSERT_EQUALS("", errout.str());
check("struct A {};\n"
"void f() {\n"
" std::vector<std::shared_ptr<A>> v;\n"
" std::shared_ptr<A> a = std::make_shared<A>();\n"
" v.push_back(a);\n"
" std::shared_ptr<A> b = v.back();\n"
" v.pop_back();\n"
" delete b;\n"
"}\n" ,true);
ASSERT_EQUALS("", errout.str());
} }
void invalidContainerLoop() { void invalidContainerLoop() {