Fix issue 9712: False positive: Returning pointer to local variable when return line implicitly cast to return type (#2662)

This commit is contained in:
Paul Fultz II 2020-05-23 16:12:00 -05:00 committed by GitHub
parent 084529575f
commit bbe6157e16
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 55 additions and 4 deletions

View File

@ -2977,11 +2977,47 @@ static bool isLifetimeBorrowed(const ValueType *vt, const ValueType *vtParent)
return true;
if (vtParent->pointer < vt->pointer && vtParent->isIntegral())
return true;
if (vtParent->str() == vt->str())
return true;
}
return false;
}
static const Token* skipCVRefs(const Token* tok, const Token* endTok)
{
while(tok != endTok && Token::Match(tok, "const|volatile|auto|&|&&"))
tok = tok->next();
return tok;
}
static bool isNotEqual(std::pair<const Token*, const Token*> x, std::pair<const Token*, const Token*> y)
{
const Token* start1 = x.first;
const Token* start2 = y.first;
if (start1 == nullptr || start2 == nullptr)
return false;
while(start1 != x.second && start2 != y.second) {
const Token* tok1 = skipCVRefs(start1, x.second);
if (tok1 != start1) {
start1 = tok1;
continue;
}
const Token* tok2 = skipCVRefs(start2, y.second);
if (tok2 != start2) {
start2 = tok2;
continue;
}
if (start1->str() != start2->str())
return true;
start1 = start1->next();
start2 = start2->next();
}
start1 = skipCVRefs(start1, x.second);
start2 = skipCVRefs(start2, y.second);
return !(start1 == x.second && start2 == y.second);
}
bool isLifetimeBorrowed(const Token *tok, const Settings *settings)
{
if (!tok)
@ -2999,10 +3035,18 @@ bool isLifetimeBorrowed(const Token *tok, const Settings *settings)
if (isLifetimeOwned(vt, vtParent))
return false;
}
const Type *t = Token::typeOf(tok);
const Type *parentT = Token::typeOf(tok->astParent());
if (t && parentT && t->classDef && parentT->classDef && t->classDef != parentT->classDef) {
return false;
if (Token::Match(tok->astParent(), "return|(|{|%assign%")) {
const Type *t = Token::typeOf(tok);
const Type *parentT = Token::typeOf(tok->astParent());
if (t && parentT) {
if (t->classDef && parentT->classDef && t->classDef != parentT->classDef)
return false;
} else {
std::pair<const Token*, const Token*> decl = Token::typeDecl(tok);
std::pair<const Token*, const Token*> parentdecl = Token::typeDecl(tok->astParent());
if (isNotEqual(decl, parentdecl))
return false;
}
}
} else if (Token::Match(tok->astParent()->tokAt(-3), "%var% . push_back|push_front|insert|push (") &&
astIsContainer(tok->astParent()->tokAt(-3))) {

View File

@ -2320,6 +2320,13 @@ private:
" return &y.x[i];\n"
"}\n");
ASSERT_EQUALS("", errout.str());
// #9712
check("std::string f(const char *str) {\n"
" char value[256];\n"
" return value;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
void danglingLifetimeFunction() {