Fixed #6867 (False positive memleak)

This commit is contained in:
Daniel Marjamäki 2015-07-25 11:37:03 +02:00
parent 53d7620b1a
commit e5151a13ab
5 changed files with 53 additions and 32 deletions

View File

@ -288,19 +288,38 @@ void CheckLeakAutoVar::checkScope(const Token * const startToken,
VarInfo varInfo1(*varInfo); // VarInfo for if code
VarInfo varInfo2(*varInfo); // VarInfo for else code
const Token *vartok = nullptr;
if (Token::findVariableComparison(tok->next()->astOperand2(), "!=", "0", &vartok)) {
varInfo2.erase(vartok->varId());
if (notzero.find(vartok->varId()) != notzero.end())
varInfo2.clear();
} else if (Token::findVariableComparison(tok->next()->astOperand2(), "==", "0", &vartok)) {
varInfo1.erase(vartok->varId());
} else if (Token::findVariableComparison(tok->next()->astOperand2(), "<", "0", &vartok)) {
varInfo1.erase(vartok->varId());
} else if (Token::findVariableComparison(tok->next()->astOperand2(), ">", "0", &vartok)) {
varInfo2.erase(vartok->varId());
} else if (Token::findVariableComparison(tok->next()->astOperand2(), "==", "-1", &vartok)) {
varInfo1.erase(vartok->varId());
// Recursively scan variable comparisons in condition
std::stack<const Token *> tokens;
tokens.push(tok->next()->astOperand2());
while (!tokens.empty()) {
const Token *tok3 = tokens.top();
tokens.pop();
if (!tok3)
continue;
if (tok3->str() == "&&") {
tokens.push(tok3->astOperand1());
tokens.push(tok3->astOperand2());
continue;
}
if (tok3->str() == "(" && Token::Match(tok3->astOperand1(), "UNLIKELY|LIKELY")) {
tokens.push(tok3->astOperand2());
continue;
}
const Token *vartok = nullptr;
if (Token::isVariableComparison(tok3, "!=", "0", &vartok)) {
varInfo2.erase(vartok->varId());
if (notzero.find(vartok->varId()) != notzero.end())
varInfo2.clear();
} else if (Token::isVariableComparison(tok3, "==", "0", &vartok)) {
varInfo1.erase(vartok->varId());
} else if (Token::isVariableComparison(tok3, "<", "0", &vartok)) {
varInfo1.erase(vartok->varId());
} else if (Token::isVariableComparison(tok3, ">", "0", &vartok)) {
varInfo2.erase(vartok->varId());
} else if (Token::isVariableComparison(tok3, "==", "-1", &vartok)) {
varInfo1.erase(vartok->varId());
}
}
checkScope(tok2->next(), &varInfo1, notzero);

View File

@ -519,11 +519,13 @@ const char *CheckMemoryLeak::functionArgAlloc(const Function *func, unsigned int
static bool notvar(const Token *tok, unsigned int varid)
{
if (!tok)
return false;
if (Token::Match(tok, "&&|;"))
return notvar(tok->astOperand1(),varid) || notvar(tok->astOperand2(),varid);
const Token *vartok = Token::findVariableComparison(tok, "==", "0");
if (tok->str() == "(" && Token::Match(tok->astOperand1(), "UNLIKELY|LIKELY"))
return notvar(tok->astOperand2(), varid);
const Token *vartok = Token::isVariableComparison(tok, "==", "0");
return vartok && (vartok->varId() == varid);
}
@ -531,11 +533,13 @@ static bool ifvar(const Token *tok, unsigned int varid, const std::string &comp,
{
if (!Token::simpleMatch(tok, "if ("))
return false;
const Token * const condition = tok->next()->astOperand2();
const Token *condition = tok->next()->astOperand2();
if (condition && condition->str() == "(" && Token::Match(condition->astOperand1(), "UNLIKELY|LIKELY"))
condition = condition->astOperand2();
if (!condition || condition->str() == "&&")
return false;
const Token *vartok = nullptr;
Token::findVariableComparison(condition, comp, rhs, &vartok);
const Token *vartok = Token::isVariableComparison(condition, comp, rhs);
return (vartok && vartok->varId() == varid);
}

View File

@ -1460,21 +1460,11 @@ const Token *Token::getValueTokenDeadPointer() const
}
const Token * Token::findVariableComparison(const Token *tok, const std::string &comp, const std::string &rhs, const Token **vartok)
const Token * Token::isVariableComparison(const Token *tok, const std::string &comp, const std::string &rhs, const Token **vartok)
{
if (!tok)
return nullptr;
if (tok->str() == "&&") {
const Token *ret = findVariableComparison(tok->astOperand1(), comp, rhs, vartok);
if (!ret)
ret = findVariableComparison(tok->astOperand2(), comp, rhs, vartok);
return ret;
}
if (tok->str() == "(" && tok->astOperand2() && Token::Match(tok->astOperand1(), "UNLIKELY|LIKELY"))
return findVariableComparison(tok->astOperand2(), comp, rhs, vartok);
const Token *ret = nullptr;
if (tok->isComparisonOp()) {
if (tok->astOperand1() && tok->astOperand1()->str() == rhs) {

View File

@ -717,8 +717,8 @@ public:
const Token *getValueTokenDeadPointer() const;
/** Recursively search for variable comparison against value */
static const Token * findVariableComparison(const Token *tok, const std::string &comp, const std::string &rhs, const Token **vartok=nullptr);
/** Is given syntax tree a variable comparison against value */
static const Token * isVariableComparison(const Token *tok, const std::string &comp, const std::string &rhs, const Token **vartok=nullptr);
private:

View File

@ -869,6 +869,14 @@ private:
"}");
ASSERT_EQUALS("", errout.str());
check("char * f(size_t size) {"
" void *p = malloc(1);"
" if (!p && size != 0)"
" return NULL;"
" return p;"
"}");
ASSERT_EQUALS("", errout.str());
check("void f() {\n"
" char *p = malloc(10);\n"
" if (p) { } else { return; }\n"