Fixed #6867 (False positive memleak)
This commit is contained in:
parent
53d7620b1a
commit
e5151a13ab
|
@ -288,20 +288,39 @@ void CheckLeakAutoVar::checkScope(const Token * const startToken,
|
||||||
VarInfo varInfo1(*varInfo); // VarInfo for if code
|
VarInfo varInfo1(*varInfo); // VarInfo for if code
|
||||||
VarInfo varInfo2(*varInfo); // VarInfo for else code
|
VarInfo varInfo2(*varInfo); // VarInfo for else code
|
||||||
|
|
||||||
|
// 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;
|
const Token *vartok = nullptr;
|
||||||
if (Token::findVariableComparison(tok->next()->astOperand2(), "!=", "0", &vartok)) {
|
if (Token::isVariableComparison(tok3, "!=", "0", &vartok)) {
|
||||||
varInfo2.erase(vartok->varId());
|
varInfo2.erase(vartok->varId());
|
||||||
if (notzero.find(vartok->varId()) != notzero.end())
|
if (notzero.find(vartok->varId()) != notzero.end())
|
||||||
varInfo2.clear();
|
varInfo2.clear();
|
||||||
} else if (Token::findVariableComparison(tok->next()->astOperand2(), "==", "0", &vartok)) {
|
} else if (Token::isVariableComparison(tok3, "==", "0", &vartok)) {
|
||||||
varInfo1.erase(vartok->varId());
|
varInfo1.erase(vartok->varId());
|
||||||
} else if (Token::findVariableComparison(tok->next()->astOperand2(), "<", "0", &vartok)) {
|
} else if (Token::isVariableComparison(tok3, "<", "0", &vartok)) {
|
||||||
varInfo1.erase(vartok->varId());
|
varInfo1.erase(vartok->varId());
|
||||||
} else if (Token::findVariableComparison(tok->next()->astOperand2(), ">", "0", &vartok)) {
|
} else if (Token::isVariableComparison(tok3, ">", "0", &vartok)) {
|
||||||
varInfo2.erase(vartok->varId());
|
varInfo2.erase(vartok->varId());
|
||||||
} else if (Token::findVariableComparison(tok->next()->astOperand2(), "==", "-1", &vartok)) {
|
} else if (Token::isVariableComparison(tok3, "==", "-1", &vartok)) {
|
||||||
varInfo1.erase(vartok->varId());
|
varInfo1.erase(vartok->varId());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
checkScope(tok2->next(), &varInfo1, notzero);
|
checkScope(tok2->next(), &varInfo1, notzero);
|
||||||
tok2 = tok2->linkAt(1);
|
tok2 = tok2->linkAt(1);
|
||||||
|
|
|
@ -519,11 +519,13 @@ const char *CheckMemoryLeak::functionArgAlloc(const Function *func, unsigned int
|
||||||
|
|
||||||
static bool notvar(const Token *tok, unsigned int varid)
|
static bool notvar(const Token *tok, unsigned int varid)
|
||||||
{
|
{
|
||||||
|
if (!tok)
|
||||||
|
return false;
|
||||||
if (Token::Match(tok, "&&|;"))
|
if (Token::Match(tok, "&&|;"))
|
||||||
return notvar(tok->astOperand1(),varid) || notvar(tok->astOperand2(),varid);
|
return notvar(tok->astOperand1(),varid) || notvar(tok->astOperand2(),varid);
|
||||||
|
if (tok->str() == "(" && Token::Match(tok->astOperand1(), "UNLIKELY|LIKELY"))
|
||||||
const Token *vartok = Token::findVariableComparison(tok, "==", "0");
|
return notvar(tok->astOperand2(), varid);
|
||||||
|
const Token *vartok = Token::isVariableComparison(tok, "==", "0");
|
||||||
return vartok && (vartok->varId() == varid);
|
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 ("))
|
if (!Token::simpleMatch(tok, "if ("))
|
||||||
return false;
|
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() == "&&")
|
if (!condition || condition->str() == "&&")
|
||||||
return false;
|
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);
|
return (vartok && vartok->varId() == varid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
if (!tok)
|
||||||
return nullptr;
|
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;
|
const Token *ret = nullptr;
|
||||||
if (tok->isComparisonOp()) {
|
if (tok->isComparisonOp()) {
|
||||||
if (tok->astOperand1() && tok->astOperand1()->str() == rhs) {
|
if (tok->astOperand1() && tok->astOperand1()->str() == rhs) {
|
||||||
|
|
|
@ -717,8 +717,8 @@ public:
|
||||||
|
|
||||||
const Token *getValueTokenDeadPointer() const;
|
const Token *getValueTokenDeadPointer() const;
|
||||||
|
|
||||||
/** Recursively search for variable comparison against value */
|
/** Is given syntax tree a variable comparison against value */
|
||||||
static const Token * findVariableComparison(const Token *tok, const std::string &comp, const std::string &rhs, const Token **vartok=nullptr);
|
static const Token * isVariableComparison(const Token *tok, const std::string &comp, const std::string &rhs, const Token **vartok=nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -869,6 +869,14 @@ private:
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("", errout.str());
|
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"
|
check("void f() {\n"
|
||||||
" char *p = malloc(10);\n"
|
" char *p = malloc(10);\n"
|
||||||
" if (p) { } else { return; }\n"
|
" if (p) { } else { return; }\n"
|
||||||
|
|
Loading…
Reference in New Issue