Fix #9206 (FP with global variable allocated in condition) (#2007)

This commit is contained in:
Rikard Falkeborn 2019-07-17 07:43:07 +02:00 committed by Daniel Marjamäki
parent 413a5a4865
commit 8513fb81d2
2 changed files with 46 additions and 18 deletions

View File

@ -206,6 +206,30 @@ static bool isPointerReleased(const Token *startToken, const Token *endToken, no
return false; return false;
} }
static bool checkVariable(const Token *varTok, const bool isCpp)
{
// not a local variable nor argument?
const Variable *var = varTok->variable();
if (var && !var->isArgument() && (!var->isLocal() || var->isStatic()))
return false;
// Don't check reference variables
if (var && var->isReference())
return false;
// non-pod variable
if (isCpp) {
if (!var)
return false;
// Possibly automatically deallocated memory
if (!var->typeStartToken()->isStandardType() && Token::Match(varTok, "%var% = new"))
return false;
if (!var->isPointer() && !var->typeStartToken()->isStandardType())
return false;
}
return true;
}
/** checks if nameToken is a name of a function in a function call: /** checks if nameToken is a name of a function in a function call:
* func(arg) * func(arg)
* or * or
@ -318,26 +342,9 @@ void CheckLeakAutoVar::checkScope(const Token * const startToken,
leakIfAllocated(varTok, *varInfo); leakIfAllocated(varTok, *varInfo);
varInfo->erase(varTok->varId()); varInfo->erase(varTok->varId());
// not a local variable nor argument? if (!checkVariable(varTok, mTokenizer->isCPP()))
const Variable *var = varTok->variable();
if (var && !var->isArgument() && (!var->isLocal() || var->isStatic()))
continue; continue;
// Don't check reference variables
if (var && var->isReference())
continue;
// non-pod variable
if (mTokenizer->isCPP()) {
if (!var)
continue;
// Possibly automatically deallocated memory
if (!var->typeStartToken()->isStandardType() && Token::Match(varTok, "%var% = new"))
continue;
if (!var->isPointer() && !var->typeStartToken()->isStandardType())
continue;
}
// allocation? // allocation?
const Token *const fTok = tokRightAstOperand ? tokRightAstOperand->previous() : nullptr; const Token *const fTok = tokRightAstOperand ? tokRightAstOperand->previous() : nullptr;
if (Token::Match(fTok, "%type% (")) { if (Token::Match(fTok, "%type% (")) {
@ -375,6 +382,9 @@ void CheckLeakAutoVar::checkScope(const Token * const startToken,
for (const Token *innerTok = tok->tokAt(2); innerTok && innerTok != closingParenthesis; innerTok = innerTok->next()) { for (const Token *innerTok = tok->tokAt(2); innerTok && innerTok != closingParenthesis; innerTok = innerTok->next()) {
// TODO: replace with checkTokenInsideExpression() // TODO: replace with checkTokenInsideExpression()
if (!checkVariable(innerTok, mTokenizer->isCPP()))
continue;
if (Token::Match(innerTok, "%var% =") && innerTok->astParent() == innerTok->next()) { if (Token::Match(innerTok, "%var% =") && innerTok->astParent() == innerTok->next()) {
// allocation? // allocation?
// right ast part (after `=` operator) // right ast part (after `=` operator)

View File

@ -121,6 +121,7 @@ private:
TEST_CASE(ifelse12); // #8340 - if ((*p = malloc(4)) == NULL) TEST_CASE(ifelse12); // #8340 - if ((*p = malloc(4)) == NULL)
TEST_CASE(ifelse13); // #8392 TEST_CASE(ifelse13); // #8392
TEST_CASE(ifelse14); // #9130 - if (x == (char*)NULL) TEST_CASE(ifelse14); // #9130 - if (x == (char*)NULL)
TEST_CASE(ifelse15); // #9206 - if (global_ptr = malloc(1))
// switch // switch
TEST_CASE(switch1); TEST_CASE(switch1);
@ -1364,6 +1365,23 @@ private:
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void ifelse15() { // #9206
check("struct SSS { int a; };\n"
"SSS* global_ptr;\n"
"void test_alloc() {\n"
" if ( global_ptr = new SSS()) {}\n"
" return;\n"
"}", true);
ASSERT_EQUALS("", errout.str());
check("FILE* hFile;\n"
"int openFile( void ) {\n"
" if ((hFile = fopen(\"1.txt\", \"wb\" )) == NULL) return 0;\n"
" return 1;\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void switch1() { void switch1() {
check("void f() {\n" check("void f() {\n"
" char *p = 0;\n" " char *p = 0;\n"