Fix #10187 (memleak open with fd >= 0) (#3156)

This commit is contained in:
Rikard Falkeborn 2021-03-03 07:00:28 +01:00 committed by GitHub
parent 42a41e8b41
commit 27316e04ed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 37 additions and 21 deletions

View File

@ -52,6 +52,8 @@ static const CWE CWE415(415U);
static const int NEW_ARRAY = -2;
static const int NEW = -1;
static const std::vector<std::pair<std::string, std::string>> alloc_failed_conds {{"==", "0"}, {"<", "0"}, {"==", "-1"}, {"<=", "-1"}};
static const std::vector<std::pair<std::string, std::string>> alloc_success_conds {{"!=", "0"}, {">", "0"}, {"!=", "-1"}, {">=", "0"}};
/**
* @brief Is variable type some class with automatic deallocation?
@ -75,6 +77,16 @@ static bool isAutoDealloc(const Variable *var)
return true;
}
static bool isVarTokComparison(const Token * tok, const Token ** vartok,
const std::vector<std::pair<std::string, std::string>>& ops)
{
for (const auto & op : ops) {
if (astIsVariableComparison(tok, op.first, op.second, vartok))
return true;
}
return false;
}
//---------------------------------------------------------------------------
void VarInfo::print()
@ -475,12 +487,8 @@ void CheckLeakAutoVar::checkScope(const Token * const startToken,
if (!par->isComparisonOp())
continue;
const Token *vartok = nullptr;
if (astIsVariableComparison(par, "!=", "0", &vartok) ||
astIsVariableComparison(par, "==", "0", &vartok) ||
astIsVariableComparison(par, "<", "0", &vartok) ||
astIsVariableComparison(par, ">", "0", &vartok) ||
astIsVariableComparison(par, "==", "-1", &vartok) ||
astIsVariableComparison(par, "!=", "-1", &vartok)) {
if (isVarTokComparison(par, &vartok, alloc_success_conds) ||
(isVarTokComparison(par, &vartok, alloc_failed_conds))) {
varInfo1.erase(vartok->varId());
varInfo2.erase(vartok->varId());
}
@ -489,26 +497,15 @@ void CheckLeakAutoVar::checkScope(const Token * const startToken,
}
const Token *vartok = nullptr;
if (astIsVariableComparison(tok3, "!=", "0", &vartok)) {
if (isVarTokComparison(tok3, &vartok, alloc_success_conds)) {
varInfo2.reallocToAlloc(vartok->varId());
varInfo2.erase(vartok->varId());
if (notzero.find(vartok->varId()) != notzero.end())
if (astIsVariableComparison(tok3, "!=", "0", &vartok) &&
(notzero.find(vartok->varId()) != notzero.end()))
varInfo2.clear();
} else if (astIsVariableComparison(tok3, "==", "0", &vartok)) {
} else if (isVarTokComparison(tok3, &vartok, alloc_failed_conds)) {
varInfo1.reallocToAlloc(vartok->varId());
varInfo1.erase(vartok->varId());
} else if (astIsVariableComparison(tok3, "<", "0", &vartok)) {
varInfo1.reallocToAlloc(vartok->varId());
varInfo1.erase(vartok->varId());
} else if (astIsVariableComparison(tok3, ">", "0", &vartok)) {
varInfo2.reallocToAlloc(vartok->varId());
varInfo2.erase(vartok->varId());
} else if (astIsVariableComparison(tok3, "==", "-1", &vartok)) {
varInfo1.reallocToAlloc(vartok->varId());
varInfo1.erase(vartok->varId());
} else if (astIsVariableComparison(tok3, "!=", "-1", &vartok)) {
varInfo2.reallocToAlloc(vartok->varId());
varInfo2.erase(vartok->varId());
}
return ChildrenToVisit::none;
});

View File

@ -148,6 +148,7 @@ private:
TEST_CASE(ifelse19);
TEST_CASE(ifelse20); // #10182
TEST_CASE(ifelse21);
TEST_CASE(ifelse22); // #10187
// switch
TEST_CASE(switch1);
@ -1659,6 +1660,24 @@ private:
ASSERT_EQUALS("[test.c:6]: (error) Memory leak: p\n", errout.str());
}
void ifelse22() { // #10187
check("int f(const char * pathname, int flags) {\n"
" int fd = socket(pathname, flags);\n"
" if (fd >= 0)\n"
" return fd;\n"
" return -1;\n"
"}");
ASSERT_EQUALS("", errout.str());
check("int f(const char * pathname, int flags) {\n"
" int fd = socket(pathname, flags);\n"
" if (fd <= -1)\n"
" return -1;\n"
" return fd;\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void switch1() {
check("void f() {\n"
" char *p = 0;\n"