This commit is contained in:
parent
1ce901385a
commit
85172fe770
|
@ -106,7 +106,7 @@ void VarInfo::print()
|
||||||
std::string strusage;
|
std::string strusage;
|
||||||
const auto use = possibleUsage.find(it->first);
|
const auto use = possibleUsage.find(it->first);
|
||||||
if (use != possibleUsage.end())
|
if (use != possibleUsage.end())
|
||||||
strusage = use->second.first;
|
strusage = use->second.first->str();
|
||||||
|
|
||||||
std::string status;
|
std::string status;
|
||||||
switch (it->second.status) {
|
switch (it->second.status) {
|
||||||
|
@ -140,7 +140,7 @@ void VarInfo::print()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VarInfo::possibleUsageAll(const std::pair<std::string, Usage>& functionUsage)
|
void VarInfo::possibleUsageAll(const std::pair<const Token*, Usage>& functionUsage)
|
||||||
{
|
{
|
||||||
possibleUsage.clear();
|
possibleUsage.clear();
|
||||||
for (std::map<int, AllocInfo>::const_iterator it = alloctype.cbegin(); it != alloctype.cend(); ++it)
|
for (std::map<int, AllocInfo>::const_iterator it = alloctype.cbegin(); it != alloctype.cend(); ++it)
|
||||||
|
@ -176,13 +176,15 @@ void CheckLeakAutoVar::deallocReturnError(const Token *tok, const Token *dealloc
|
||||||
reportError(locations, Severity::error, "deallocret", "$symbol:" + varname + "\nReturning/dereferencing '$symbol' after it is deallocated / released", CWE672, Certainty::normal);
|
reportError(locations, Severity::error, "deallocret", "$symbol:" + varname + "\nReturning/dereferencing '$symbol' after it is deallocated / released", CWE672, Certainty::normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckLeakAutoVar::configurationInfo(const Token* tok, const std::pair<std::string, VarInfo::Usage>& functionUsage)
|
void CheckLeakAutoVar::configurationInfo(const Token* tok, const std::pair<const Token*, VarInfo::Usage>& functionUsage)
|
||||||
{
|
{
|
||||||
if (mSettings->checkLibrary && functionUsage.second == VarInfo::USED) {
|
if (mSettings->checkLibrary && functionUsage.second == VarInfo::USED &&
|
||||||
|
(!functionUsage.first || !functionUsage.first->function() || !functionUsage.first->function()->hasBody())) {
|
||||||
|
const std::string funcStr = functionUsage.first ? mSettings->library.getFunctionName(functionUsage.first) : "f";
|
||||||
reportError(tok,
|
reportError(tok,
|
||||||
Severity::information,
|
Severity::information,
|
||||||
"checkLibraryUseIgnore",
|
"checkLibraryUseIgnore",
|
||||||
"--check-library: Function " + functionUsage.first + "() should have <use>/<leak-ignore> configuration");
|
"--check-library: Function " + funcStr + "() should have <use>/<leak-ignore> configuration");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -684,7 +686,6 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
|
||||||
if (allocation.status == VarInfo::NOALLOC && Token::simpleMatch(tok, ") ; }")) {
|
if (allocation.status == VarInfo::NOALLOC && Token::simpleMatch(tok, ") ; }")) {
|
||||||
if (ftok->isKeyword())
|
if (ftok->isKeyword())
|
||||||
continue;
|
continue;
|
||||||
const std::string functionName(mSettings->library.getFunctionName(ftok));
|
|
||||||
bool unknown = false;
|
bool unknown = false;
|
||||||
if (mTokenizer->isScopeNoReturn(tok->tokAt(2), &unknown)) {
|
if (mTokenizer->isScopeNoReturn(tok->tokAt(2), &unknown)) {
|
||||||
if (!unknown)
|
if (!unknown)
|
||||||
|
@ -693,9 +694,10 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
|
||||||
if (ftok->function() && !ftok->function()->isAttributeNoreturn() &&
|
if (ftok->function() && !ftok->function()->isAttributeNoreturn() &&
|
||||||
!(ftok->function()->functionScope && mTokenizer->isScopeNoReturn(ftok->function()->functionScope->bodyEnd))) // check function scope
|
!(ftok->function()->functionScope && mTokenizer->isScopeNoReturn(ftok->function()->functionScope->bodyEnd))) // check function scope
|
||||||
continue;
|
continue;
|
||||||
|
const std::string functionName(mSettings->library.getFunctionName(ftok));
|
||||||
if (!mSettings->library.isLeakIgnore(functionName) && !mSettings->library.isUse(functionName)) {
|
if (!mSettings->library.isLeakIgnore(functionName) && !mSettings->library.isUse(functionName)) {
|
||||||
const VarInfo::Usage usage = Token::simpleMatch(openingPar, "( )") ? VarInfo::NORET : VarInfo::USED; // TODO: check parameters passed to function
|
const VarInfo::Usage usage = Token::simpleMatch(openingPar, "( )") ? VarInfo::NORET : VarInfo::USED; // TODO: check parameters passed to function
|
||||||
varInfo.possibleUsageAll({ functionName, usage });
|
varInfo.possibleUsageAll({ ftok, usage });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -895,7 +897,7 @@ void CheckLeakAutoVar::changeAllocStatus(VarInfo &varInfo, const VarInfo::AllocI
|
||||||
if (var != alloctype.end()) {
|
if (var != alloctype.end()) {
|
||||||
if (allocation.status == VarInfo::NOALLOC) {
|
if (allocation.status == VarInfo::NOALLOC) {
|
||||||
// possible usage
|
// possible usage
|
||||||
varInfo.possibleUsage[arg->varId()] = { tok->str(), VarInfo::USED };
|
varInfo.possibleUsage[arg->varId()] = { tok, VarInfo::USED };
|
||||||
if (var->second.status == VarInfo::DEALLOC && arg->previous()->str() == "&")
|
if (var->second.status == VarInfo::DEALLOC && arg->previous()->str() == "&")
|
||||||
varInfo.erase(arg->varId());
|
varInfo.erase(arg->varId());
|
||||||
} else if (var->second.managed()) {
|
} else if (var->second.managed()) {
|
||||||
|
|
|
@ -57,7 +57,7 @@ public:
|
||||||
};
|
};
|
||||||
enum Usage { USED, NORET };
|
enum Usage { USED, NORET };
|
||||||
std::map<int, AllocInfo> alloctype;
|
std::map<int, AllocInfo> alloctype;
|
||||||
std::map<int, std::pair<std::string, Usage>> possibleUsage;
|
std::map<int, std::pair<const Token*, Usage>> possibleUsage;
|
||||||
std::set<int> conditionalAlloc;
|
std::set<int> conditionalAlloc;
|
||||||
std::set<int> referenced;
|
std::set<int> referenced;
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/** set possible usage for all variables */
|
/** set possible usage for all variables */
|
||||||
void possibleUsageAll(const std::pair<std::string, Usage>& functionUsage);
|
void possibleUsageAll(const std::pair<const Token*, Usage>& functionUsage);
|
||||||
|
|
||||||
void print();
|
void print();
|
||||||
};
|
};
|
||||||
|
@ -159,12 +159,12 @@ private:
|
||||||
void doubleFreeError(const Token *tok, const Token *prevFreeTok, const std::string &varname, int type);
|
void doubleFreeError(const Token *tok, const Token *prevFreeTok, const std::string &varname, int type);
|
||||||
|
|
||||||
/** message: user configuration is needed to complete analysis */
|
/** message: user configuration is needed to complete analysis */
|
||||||
void configurationInfo(const Token* tok, const std::pair<std::string, VarInfo::Usage>& functionUsage);
|
void configurationInfo(const Token* tok, const std::pair<const Token*, VarInfo::Usage>& functionUsage);
|
||||||
|
|
||||||
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override {
|
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override {
|
||||||
CheckLeakAutoVar c(nullptr, settings, errorLogger);
|
CheckLeakAutoVar c(nullptr, settings, errorLogger);
|
||||||
c.deallocReturnError(nullptr, nullptr, "p");
|
c.deallocReturnError(nullptr, nullptr, "p");
|
||||||
c.configurationInfo(nullptr, { "f", VarInfo::USED }); // user configuration is needed to complete analysis
|
c.configurationInfo(nullptr, { nullptr, VarInfo::USED }); // user configuration is needed to complete analysis
|
||||||
c.doubleFreeError(nullptr, nullptr, "varname", 0);
|
c.doubleFreeError(nullptr, nullptr, "varname", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2828,6 +2828,16 @@ private:
|
||||||
" SomeClass::someMethod(a);\n"
|
" SomeClass::someMethod(a);\n"
|
||||||
"}\n", settingsLeakIgnore);
|
"}\n", settingsLeakIgnore);
|
||||||
ASSERT_EQUALS("[test.cpp:4]: (error) Memory leak: a\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:4]: (error) Memory leak: a\n", errout.str());
|
||||||
|
|
||||||
|
check("void bar(int* p) {\n"
|
||||||
|
" if (p)\n"
|
||||||
|
" free(p);\n"
|
||||||
|
"}\n"
|
||||||
|
"void f() {\n"
|
||||||
|
" int* p = malloc(4);\n"
|
||||||
|
" bar(p);\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue