Fix 10592: False positive: returnDanglingLifetime (#3557)

This commit is contained in:
Paul Fultz II 2021-11-11 01:00:05 -06:00 committed by GitHub
parent 0d1d3b4ed0
commit c057dcce0f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 36 additions and 12 deletions

9
lib/astutils.cpp Normal file → Executable file
View File

@ -259,6 +259,15 @@ bool astIsSmartPointer(const Token* tok)
return tok && tok->valueType() && tok->valueType()->smartPointerTypeToken;
}
bool astIsUniqueSmartPointer(const Token* tok)
{
if (!astIsSmartPointer(tok))
return false;
if (!tok->valueType()->smartPointer)
return false;
return tok->valueType()->smartPointer->unique;
}
bool astIsIterator(const Token *tok)
{
return tok && tok->valueType() && tok->valueType()->type == ValueType::Type::ITERATOR;

1
lib/astutils.h Normal file → Executable file
View File

@ -82,6 +82,7 @@ bool astIsBool(const Token *tok);
bool astIsPointer(const Token *tok);
bool astIsSmartPointer(const Token* tok);
bool astIsUniqueSmartPointer(const Token* tok);
bool astIsIterator(const Token *tok);

15
lib/checkautovariables.cpp Normal file → Executable file
View File

@ -557,6 +557,21 @@ static const Token* getParentLifetime(bool cpp, const Token* tok, const Library*
if (std::any_of(it.base() - 1, members.end() - 1, [&](const Token* tok2) {
if (astIsPointer(tok2) || astIsContainerView(tok2) || astIsIterator(tok2))
return true;
if (!astIsUniqueSmartPointer(tok2)) {
if (astIsSmartPointer(tok2))
return true;
const Token* dotTok = tok2->next();
if (!Token::simpleMatch(dotTok, ".")) {
const Token* endTok = nextAfterAstRightmostLeaf(tok2);
if (Token::simpleMatch(endTok, "."))
dotTok = endTok;
else if (Token::simpleMatch(endTok->next(), "."))
dotTok = endTok->next();
}
// If we are dereferencing the member variable then treat it as borrowed
if (Token::simpleMatch(dotTok, ".") && dotTok->originalName() == "->")
return true;
}
const Variable* var = tok2->variable();
return var && var->isReference();
}))

14
lib/valueflow.cpp Normal file → Executable file
View File

@ -2885,15 +2885,6 @@ static void valueFlowReverse(TokenList* tokenlist,
valueFlowReverse(tok, nullptr, varToken, values, tokenlist, settings);
}
static bool isUniqueSmartPointer(const Token* tok)
{
if (!astIsSmartPointer(tok))
return false;
if (!tok->valueType()->smartPointer)
return false;
return tok->valueType()->smartPointer->unique;
}
std::string lifetimeType(const Token *tok, const ValueFlow::Value *val)
{
std::string result;
@ -3090,8 +3081,7 @@ static std::vector<LifetimeToken> getLifetimeTokens(const Token* tok,
return {{tok, std::move(errorPath)}};
const Variable *tokvar = vartok->variable();
const bool isContainer = astIsContainer(vartok) && !astIsPointer(vartok);
if (!isUniqueSmartPointer(vartok) && !isContainer &&
!(tokvar && tokvar->isArray() && !tokvar->isArgument()) &&
if (!astIsUniqueSmartPointer(vartok) && !isContainer && !(tokvar && tokvar->isArray() && !tokvar->isArgument()) &&
(Token::Match(vartok->astParent(), "[|*") || vartok->astParent()->originalName() == "->")) {
for (const ValueFlow::Value &v : vartok->values()) {
if (!v.isLocalLifetimeValue())
@ -4158,7 +4148,7 @@ static void valueFlowLifetime(TokenList *tokenlist, SymbolDatabase*, ErrorLogger
valueFlowLifetimeFunction(tok, tokenlist, errorLogger, settings);
}
// Unique pointer lifetimes
else if (isUniqueSmartPointer(tok) && astIsLHS(tok) && Token::simpleMatch(tok->astParent(), ". get ( )")) {
else if (astIsUniqueSmartPointer(tok) && astIsLHS(tok) && Token::simpleMatch(tok->astParent(), ". get ( )")) {
Token* ptok = tok->astParent()->tokAt(2);
ErrorPath errorPath = {{ptok, "Raw pointer to smart pointer created here."}};
ValueFlow::Value value;

9
test/testautovariables.cpp Normal file → Executable file
View File

@ -2482,6 +2482,15 @@ private:
" }\n"
"};\n");
ASSERT_EQUALS("", errout.str());
check("struct A {\n"
" std::map<std::string, int> m;\n"
" int* f(std::string s) {\n"
" auto r = m.emplace(name, name);\n"
" return &(r.first->second);\n"
" }\n"
"};\n");
ASSERT_EQUALS("", errout.str());
}
void danglingLifetimeContainerView()