Refactorization: Support Types that consist of more than a single token in CheckMemoryLeakNoVar::checkForUnsafeArgAlloc

Removed obsolete comments
This commit is contained in:
PKEuS 2015-11-19 15:29:15 +01:00
parent 4d3e231bd0
commit db6174bb60
2 changed files with 27 additions and 17 deletions

View File

@ -799,7 +799,6 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
} else { } else {
alloc = getAllocationType(tok->tokAt(2), varid); alloc = getAllocationType(tok->tokAt(2), varid);
} }
//bool realloc = false;
if (sz > 1 && if (sz > 1 &&
Token::Match(tok->tokAt(2), "malloc ( %num% )") && Token::Match(tok->tokAt(2), "malloc ( %num% )") &&
@ -812,8 +811,6 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
if (alloc != CheckMemoryLeak::No) { if (alloc != CheckMemoryLeak::No) {
addtoken(&rettail, tok, "realloc"); addtoken(&rettail, tok, "realloc");
addtoken(&rettail, tok, ";"); addtoken(&rettail, tok, ";");
//TODO: this assignment is redundant, should be fixed
//realloc = true;
tok = tok->tokAt(2); tok = tok->tokAt(2);
if (Token::Match(tok, "%name% (")) if (Token::Match(tok, "%name% ("))
tok = tok->next()->link(); tok = tok->next()->link();
@ -845,7 +842,6 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
} }
if (alloc != No) { if (alloc != No) {
//if (! realloc)
addtoken(&rettail, tok, "alloc"); addtoken(&rettail, tok, "alloc");
if (alloctype != No && alloctype != alloc) if (alloctype != No && alloctype != alloc)
@ -911,8 +907,7 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
AllocType dealloc = getDeallocationType(tok, varid); AllocType dealloc = getDeallocationType(tok, varid);
if (dealloc != No && tok->str() == "fcloseall" && alloctype != dealloc) if (dealloc != No && tok->str() == "fcloseall" && alloctype != dealloc)
//TODO: this assignment is redundant, should be fixed ;
/*dealloc = No*/;
else if (dealloc != No) { else if (dealloc != No) {
addtoken(&rettail, tok, "dealloc"); addtoken(&rettail, tok, "dealloc");
@ -2712,28 +2707,38 @@ void CheckMemoryLeakNoVar::checkForUnsafeArgAlloc(const Scope *scope)
for (const Token *tok = scope->classStart; tok != scope->classEnd; tok = tok->next()) { for (const Token *tok = scope->classStart; tok != scope->classEnd; tok = tok->next()) {
if (Token::Match(tok, "%name% (")) { if (Token::Match(tok, "%name% (")) {
const Token *endParamToken = tok->next()->link(); const Token *endParamToken = tok->next()->link();
std::string pointerType; const Token* pointerType = nullptr;
std::string objectType; const Token* functionCalled = nullptr;
std::string functionCalled;
// Scan through the arguments to the function call // Scan through the arguments to the function call
for (const Token *tok2 = tok->tokAt(2); tok2 && tok2 != endParamToken; tok2 = tok2->nextArgument()) { for (const Token *tok2 = tok->tokAt(2); tok2 && tok2 != endParamToken; tok2 = tok2->nextArgument()) {
const Function *func = tok2->function(); const Function *func = tok2->function();
const bool isNothrow = func && (func->isAttributeNothrow() || func->isThrow()); const bool isNothrow = func && (func->isAttributeNothrow() || func->isThrow());
if (Token::Match(tok2, "shared_ptr|unique_ptr < %name% > ( new %name%")) { if (Token::Match(tok2, "shared_ptr|unique_ptr <") && tok2->next()->link() && Token::Match(tok2->next()->link(), "> ( new %name%")) {
pointerType = tok2->str(); pointerType = tok2;
objectType = tok2->strAt(6);
} else if (!isNothrow) { } else if (!isNothrow) {
if (Token::Match(tok2, "%name% (")) if (Token::Match(tok2, "%name% ("))
functionCalled = tok2->str(); functionCalled = tok2;
else if (Token::Match(tok2, "%name% < %name% > (")) else if (tok2->isName() && tok2->next()->link() && Token::Match(tok2->next()->link(), "> ("))
functionCalled = tok2->str() + "<" + tok2->strAt(2) + ">"; functionCalled = tok2;
} }
} }
if (!pointerType.empty() && !functionCalled.empty()) if (pointerType && functionCalled) {
unsafeArgAllocError(tok, functionCalled, pointerType, objectType); std::string functionName = functionCalled->str();
if (functionCalled->strAt(1) == "<") {
functionName += '<';
for (const Token* tok2 = functionCalled->tokAt(2); tok2 != functionCalled->next()->link(); tok2 = tok2->next())
functionName += tok2->str();
functionName += '>';
}
std::string objectTypeName;
for (const Token* tok2 = pointerType->tokAt(2); tok2 != pointerType->next()->link(); tok2 = tok2->next())
objectTypeName += tok2->str();
unsafeArgAllocError(tok, functionName, pointerType->str(), objectTypeName);
}
} }
} }
} }

View File

@ -6398,6 +6398,11 @@ private:
"}"); "}");
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Unsafe allocation. If h() throws, memory could be leaked. Use make_shared<char>() instead.\n", errout.str()); ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Unsafe allocation. If h() throws, memory could be leaked. Use make_shared<char>() instead.\n", errout.str());
check("void x() {\n"
" f(shared_ptr<std::string>(new std::string(\"\")), g<std::string>());\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Unsafe allocation. If g<std::string>() throws, memory could be leaked. Use make_shared<std::string>() instead.\n", errout.str());
check("void g(int x) throw() { }\n" check("void g(int x) throw() { }\n"
"void x() {\n" "void x() {\n"
" f(g(124), shared_ptr<char>(new char));\n" " f(g(124), shared_ptr<char>(new char));\n"