Printout both the locations on double free errors, mismatching alloc/dealloc and dealloc return error.
This commit is contained in:
parent
28d13e7567
commit
bb5ac32872
|
@ -133,10 +133,10 @@ void CheckLeakAutoVar::leakError(const Token *tok, const std::string &varname, i
|
|||
checkmemleak.memleakError(tok, varname);
|
||||
}
|
||||
|
||||
void CheckLeakAutoVar::mismatchError(const Token *tok, const std::string &varname)
|
||||
void CheckLeakAutoVar::mismatchError(const Token *deallocTok, const Token *allocTok, const std::string &varname)
|
||||
{
|
||||
const CheckMemoryLeak c(mTokenizer, mErrorLogger, mSettings);
|
||||
const std::list<const Token *> callstack(1, tok);
|
||||
const std::list<const Token *> callstack = { allocTok, deallocTok };
|
||||
c.mismatchAllocDealloc(callstack, varname);
|
||||
}
|
||||
|
||||
|
@ -146,9 +146,10 @@ void CheckLeakAutoVar::deallocUseError(const Token *tok, const std::string &varn
|
|||
c.deallocuseError(tok, varname);
|
||||
}
|
||||
|
||||
void CheckLeakAutoVar::deallocReturnError(const Token *tok, const std::string &varname)
|
||||
void CheckLeakAutoVar::deallocReturnError(const Token *tok, const Token *deallocTok, const std::string &varname)
|
||||
{
|
||||
reportError(tok, Severity::error, "deallocret", "$symbol:" + varname + "\nReturning/dereferencing '$symbol' after it is deallocated / released", CWE672, false);
|
||||
const std::list<const Token *> locations = { deallocTok, tok };
|
||||
reportError(locations, Severity::error, "deallocret", "$symbol:" + varname + "\nReturning/dereferencing '$symbol' after it is deallocated / released", CWE672, false);
|
||||
}
|
||||
|
||||
void CheckLeakAutoVar::configurationInfo(const Token* tok, const std::string &functionName)
|
||||
|
@ -161,12 +162,14 @@ void CheckLeakAutoVar::configurationInfo(const Token* tok, const std::string &fu
|
|||
}
|
||||
}
|
||||
|
||||
void CheckLeakAutoVar::doubleFreeError(const Token *tok, const std::string &varname, int type)
|
||||
void CheckLeakAutoVar::doubleFreeError(const Token *tok, const Token *prevFreeTok, const std::string &varname, int type)
|
||||
{
|
||||
const std::list<const Token *> locations = { prevFreeTok, tok };
|
||||
|
||||
if (Library::isresource(type))
|
||||
reportError(tok, Severity::error, "doubleFree", "$symbol:" + varname + "\nResource handle '$symbol' freed twice.", CWE415, false);
|
||||
reportError(locations, Severity::error, "doubleFree", "$symbol:" + varname + "\nResource handle '$symbol' freed twice.", CWE415, false);
|
||||
else
|
||||
reportError(tok, Severity::error, "doubleFree", "$symbol:" + varname + "\nMemory pointed to by '$symbol' is freed twice.", CWE415, false);
|
||||
reportError(locations, Severity::error, "doubleFree", "$symbol:" + varname + "\nMemory pointed to by '$symbol' is freed twice.", CWE415, false);
|
||||
}
|
||||
|
||||
|
||||
|
@ -381,6 +384,7 @@ void CheckLeakAutoVar::checkScope(const Token * const startToken,
|
|||
VarInfo::AllocInfo& varAlloc = alloctype[varTok->varId()];
|
||||
varAlloc.type = f->groupId;
|
||||
varAlloc.status = VarInfo::ALLOC;
|
||||
varAlloc.allocTok = fTok;
|
||||
}
|
||||
|
||||
changeAllocStatusIfRealloc(alloctype, fTok, varTok);
|
||||
|
@ -390,6 +394,7 @@ void CheckLeakAutoVar::checkScope(const Token * const startToken,
|
|||
VarInfo::AllocInfo& varAlloc = alloctype[varTok->varId()];
|
||||
varAlloc.type = arrayNew ? NEW_ARRAY : NEW;
|
||||
varAlloc.status = VarInfo::ALLOC;
|
||||
varAlloc.allocTok = varTok->tokAt(2);
|
||||
}
|
||||
|
||||
// Assigning non-zero value variable. It might be used to
|
||||
|
@ -425,6 +430,7 @@ void CheckLeakAutoVar::checkScope(const Token * const startToken,
|
|||
VarInfo::AllocInfo& varAlloc = alloctype[innerTok->varId()];
|
||||
varAlloc.type = f->groupId;
|
||||
varAlloc.status = VarInfo::ALLOC;
|
||||
varAlloc.allocTok = tokRightAstOperand->previous();
|
||||
} else {
|
||||
// Fixme: warn about leak
|
||||
alloctype.erase(innerTok->varId());
|
||||
|
@ -437,6 +443,7 @@ void CheckLeakAutoVar::checkScope(const Token * const startToken,
|
|||
VarInfo::AllocInfo& varAlloc = alloctype[innerTok->varId()];
|
||||
varAlloc.type = arrayNew ? NEW_ARRAY : NEW;
|
||||
varAlloc.status = VarInfo::ALLOC;
|
||||
varAlloc.allocTok = innerTok->tokAt(2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -598,6 +605,7 @@ void CheckLeakAutoVar::checkScope(const Token * const startToken,
|
|||
|
||||
// delete
|
||||
else if (mTokenizer->isCPP() && tok->str() == "delete") {
|
||||
const Token * delTok = tok;
|
||||
const bool arrayDelete = Token::simpleMatch(tok->next(), "[ ]");
|
||||
if (arrayDelete)
|
||||
tok = tok->tokAt(3);
|
||||
|
@ -609,7 +617,7 @@ void CheckLeakAutoVar::checkScope(const Token * const startToken,
|
|||
tok = tok->tokAt(2);
|
||||
const bool isnull = tok->hasKnownIntValue() && tok->values().front().intvalue == 0;
|
||||
if (!isnull && tok->varId() && tok->strAt(1) != "[") {
|
||||
const VarInfo::AllocInfo allocation(arrayDelete ? NEW_ARRAY : NEW, VarInfo::DEALLOC);
|
||||
const VarInfo::AllocInfo allocation(arrayDelete ? NEW_ARRAY : NEW, VarInfo::DEALLOC, delTok);
|
||||
changeAllocStatus(varInfo, allocation, tok, tok);
|
||||
}
|
||||
}
|
||||
|
@ -618,7 +626,7 @@ void CheckLeakAutoVar::checkScope(const Token * const startToken,
|
|||
else if (isFunctionCall(ftok)) {
|
||||
const Token * openingPar = isFunctionCall(ftok);
|
||||
const Library::AllocFunc* af = mSettings->library.getDeallocFuncInfo(ftok);
|
||||
VarInfo::AllocInfo allocation(af ? af->groupId : 0, VarInfo::DEALLOC);
|
||||
VarInfo::AllocInfo allocation(af ? af->groupId : 0, VarInfo::DEALLOC, ftok);
|
||||
if (allocation.type == 0)
|
||||
allocation.status = VarInfo::NOALLOC;
|
||||
functionCall(ftok, openingPar, varInfo, allocation, af);
|
||||
|
@ -716,7 +724,7 @@ void CheckLeakAutoVar::checkScope(const Token * const startToken,
|
|||
}
|
||||
|
||||
const Token * vtok = typeEndTok->tokAt(3);
|
||||
const VarInfo::AllocInfo allocation(af ? af->groupId : (arrayDelete ? NEW_ARRAY : NEW), VarInfo::OWNED);
|
||||
const VarInfo::AllocInfo allocation(af ? af->groupId : (arrayDelete ? NEW_ARRAY : NEW), VarInfo::OWNED, ftok);
|
||||
changeAllocStatus(varInfo, allocation, vtok, vtok);
|
||||
}
|
||||
}
|
||||
|
@ -747,7 +755,7 @@ const Token * CheckLeakAutoVar::checkTokenInsideExpression(const Token * const t
|
|||
const Token * const openingPar = isFunctionCall(tok);
|
||||
if (openingPar) {
|
||||
const Library::AllocFunc* allocFunc = mSettings->library.getDeallocFuncInfo(tok);
|
||||
VarInfo::AllocInfo alloc(allocFunc ? allocFunc->groupId : 0, VarInfo::DEALLOC);
|
||||
VarInfo::AllocInfo alloc(allocFunc ? allocFunc->groupId : 0, VarInfo::DEALLOC, tok);
|
||||
if (alloc.type == 0)
|
||||
alloc.status = VarInfo::NOALLOC;
|
||||
functionCall(tok, openingPar, varInfo, alloc, nullptr);
|
||||
|
@ -766,10 +774,12 @@ void CheckLeakAutoVar::changeAllocStatusIfRealloc(std::map<int, VarInfo::AllocIn
|
|||
VarInfo::AllocInfo& argAlloc = alloctype[argTok->varId()];
|
||||
VarInfo::AllocInfo& retAlloc = alloctype[retTok->varId()];
|
||||
if (argAlloc.type != 0 && argAlloc.type != f->groupId)
|
||||
mismatchError(fTok, argTok->str());
|
||||
mismatchError(fTok, argAlloc.allocTok, argTok->str());
|
||||
argAlloc.status = VarInfo::DEALLOC;
|
||||
argAlloc.allocTok = fTok;
|
||||
retAlloc.type = f->groupId;
|
||||
retAlloc.status = VarInfo::ALLOC;
|
||||
retAlloc.allocTok = fTok;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -785,18 +795,20 @@ void CheckLeakAutoVar::changeAllocStatus(VarInfo *varInfo, const VarInfo::AllocI
|
|||
if (var->second.status == VarInfo::DEALLOC && arg->previous()->str() == "&")
|
||||
varInfo->erase(arg->varId());
|
||||
} else if (var->second.managed()) {
|
||||
doubleFreeError(tok, arg->str(), allocation.type);
|
||||
doubleFreeError(tok, var->second.allocTok, arg->str(), allocation.type);
|
||||
} else if (var->second.type != allocation.type) {
|
||||
// mismatching allocation and deallocation
|
||||
mismatchError(tok, arg->str());
|
||||
mismatchError(tok, var->second.allocTok, arg->str());
|
||||
varInfo->erase(arg->varId());
|
||||
} else {
|
||||
// deallocation
|
||||
var->second.status = allocation.status;
|
||||
var->second.type = allocation.type;
|
||||
var->second.allocTok = allocation.allocTok;
|
||||
}
|
||||
} else if (allocation.status != VarInfo::NOALLOC) {
|
||||
alloctype[arg->varId()].status = VarInfo::DEALLOC;
|
||||
alloctype[arg->varId()].allocTok = tok;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -844,6 +856,7 @@ void CheckLeakAutoVar::functionCall(const Token *tokName, const Token *tokOpenin
|
|||
// Check smart pointer
|
||||
else if (Token::Match(arg, "%name% < %type%") && mSettings->library.isSmartPointer(argTypeStartTok)) {
|
||||
const Token * typeEndTok = arg->linkAt(1);
|
||||
const Token * allocTok = nullptr;
|
||||
if (!Token::Match(typeEndTok, "> {|( %var% ,|)|}"))
|
||||
continue;
|
||||
|
||||
|
@ -874,15 +887,17 @@ void CheckLeakAutoVar::functionCall(const Token *tokName, const Token *tokOpenin
|
|||
const Scope * tscope = dtok->type()->classScope;
|
||||
for (const Token *tok2 = tscope->bodyStart; tok2 != tscope->bodyEnd; tok2 = tok2->next()) {
|
||||
sp_af = mSettings->library.getDeallocFuncInfo(tok2);
|
||||
if (sp_af)
|
||||
if (sp_af) {
|
||||
allocTok = tok2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Token * vtok = typeEndTok->tokAt(2);
|
||||
const VarInfo::AllocInfo sp_allocation(sp_af ? sp_af->groupId : (arrayDelete ? NEW_ARRAY : NEW), VarInfo::OWNED);
|
||||
const VarInfo::AllocInfo sp_allocation(sp_af ? sp_af->groupId : (arrayDelete ? NEW_ARRAY : NEW), VarInfo::OWNED, allocTok);
|
||||
changeAllocStatus(varInfo, sp_allocation, vtok, vtok);
|
||||
} else {
|
||||
checkTokenInsideExpression(arg, varInfo);
|
||||
|
@ -955,7 +970,7 @@ void CheckLeakAutoVar::ret(const Token *tok, const VarInfo &varInfo)
|
|||
|
||||
// return deallocated pointer
|
||||
if (used && it->second.status == VarInfo::DEALLOC)
|
||||
deallocReturnError(tok, var->name());
|
||||
deallocReturnError(tok, it->second.allocTok, var->name());
|
||||
|
||||
else if (!used && !it->second.managed()) {
|
||||
const std::map<int, std::string>::const_iterator use = possibleUsage.find(varid);
|
||||
|
|
|
@ -46,7 +46,8 @@ public:
|
|||
* checkleakautovar allocation type.
|
||||
*/
|
||||
int type;
|
||||
AllocInfo(int type_ = 0, AllocStatus status_ = NOALLOC) : status(status_), type(type_) {}
|
||||
const Token * allocTok;
|
||||
AllocInfo(int type_ = 0, AllocStatus status_ = NOALLOC, const Token* allocTok_ = nullptr) : status(status_), type(type_), allocTok(allocTok_) {}
|
||||
|
||||
bool managed() const {
|
||||
return status < 0;
|
||||
|
@ -142,19 +143,19 @@ private:
|
|||
void leakIfAllocated(const Token *vartok, const VarInfo &varInfo);
|
||||
|
||||
void leakError(const Token* tok, const std::string &varname, int type);
|
||||
void mismatchError(const Token* tok, const std::string &varname);
|
||||
void mismatchError(const Token* deallocTok, const Token* allocTok, const std::string &varname);
|
||||
void deallocUseError(const Token *tok, const std::string &varname);
|
||||
void deallocReturnError(const Token *tok, const std::string &varname);
|
||||
void doubleFreeError(const Token *tok, const std::string &varname, int type);
|
||||
void deallocReturnError(const Token *tok, const Token *deallocTok, const std::string &varname);
|
||||
void doubleFreeError(const Token *tok, const Token *prevFreeTok, const std::string &varname, int type);
|
||||
|
||||
/** message: user configuration is needed to complete analysis */
|
||||
void configurationInfo(const Token* tok, const std::string &functionName);
|
||||
|
||||
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const OVERRIDE {
|
||||
CheckLeakAutoVar c(nullptr, settings, errorLogger);
|
||||
c.deallocReturnError(nullptr, "p");
|
||||
c.deallocReturnError(nullptr, nullptr, "p");
|
||||
c.configurationInfo(nullptr, "f"); // user configuration is needed to complete analysis
|
||||
c.doubleFreeError(nullptr, "varname", 0);
|
||||
c.doubleFreeError(nullptr, nullptr, "varname", 0);
|
||||
}
|
||||
|
||||
static std::string myName() {
|
||||
|
|
|
@ -513,7 +513,7 @@ private:
|
|||
" free(p);\n"
|
||||
" return p;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.c:3]: (error) Returning/dereferencing 'p' after it is deallocated / released\n", errout.str());
|
||||
ASSERT_EQUALS("[test.c:2] -> [test.c:3]: (error) Returning/dereferencing 'p' after it is deallocated / released\n", errout.str());
|
||||
|
||||
check("void f(char *p) {\n"
|
||||
" if (!p) free(p);\n"
|
||||
|
@ -621,14 +621,14 @@ private:
|
|||
" p = 0;\n"
|
||||
" free(p);\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.c:6]: (error) Memory pointed to by 'p' is freed twice.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.c:3] -> [test.c:6]: (error) Memory pointed to by 'p' is freed twice.\n", errout.str());
|
||||
|
||||
check(
|
||||
"void foo(char *p) {\n"
|
||||
" free(p);\n"
|
||||
" free(p);\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.c:3]: (error) Memory pointed to by 'p' is freed twice.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.c:2] -> [test.c:3]: (error) Memory pointed to by 'p' is freed twice.\n", errout.str());
|
||||
|
||||
check(
|
||||
"void foo(char *p, char *r) {\n"
|
||||
|
@ -665,7 +665,7 @@ private:
|
|||
" bar();\n"
|
||||
" free(p);\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.c:4]: (error) Memory pointed to by 'p' is freed twice.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.c:2] -> [test.c:4]: (error) Memory pointed to by 'p' is freed twice.\n", errout.str());
|
||||
|
||||
check(
|
||||
"void foo(char *p) {\n"
|
||||
|
@ -673,14 +673,14 @@ private:
|
|||
" printf(\"Freed memory at location %x\", p);\n"
|
||||
" free(p);\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.c:4]: (error) Memory pointed to by 'p' is freed twice.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.c:2] -> [test.c:4]: (error) Memory pointed to by 'p' is freed twice.\n", errout.str());
|
||||
|
||||
check(
|
||||
"void foo(FILE *p) {\n"
|
||||
" fclose(p);\n"
|
||||
" fclose(p);\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.c:3]: (error) Resource handle 'p' freed twice.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.c:2] -> [test.c:3]: (error) Resource handle 'p' freed twice.\n", errout.str());
|
||||
|
||||
check(
|
||||
"void foo(FILE *p, FILE *r) {\n"
|
||||
|
@ -710,7 +710,7 @@ private:
|
|||
" gethandle();\n"
|
||||
" fclose(p);\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.c:4]: (error) Resource handle 'p' freed twice.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.c:2] -> [test.c:4]: (error) Resource handle 'p' freed twice.\n", errout.str());
|
||||
|
||||
check(
|
||||
"void foo(Data* p) {\n"
|
||||
|
@ -739,7 +739,7 @@ private:
|
|||
" }\n"
|
||||
" free(p);\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.c:7]: (error) Memory pointed to by 'p' is freed twice.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.c:4] -> [test.c:7]: (error) Memory pointed to by 'p' is freed twice.\n", errout.str());
|
||||
|
||||
check(
|
||||
"void f() {\n"
|
||||
|
@ -755,7 +755,7 @@ private:
|
|||
" delete p;\n"
|
||||
" delete p;\n"
|
||||
"}", true);
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Memory pointed to by 'p' is freed twice.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (error) Memory pointed to by 'p' is freed twice.\n", errout.str());
|
||||
|
||||
check(
|
||||
"void foo(char *p, char *r) {\n"
|
||||
|
@ -792,14 +792,14 @@ private:
|
|||
" bar();\n"
|
||||
" delete p;\n"
|
||||
"}", true);
|
||||
ASSERT_EQUALS("[test.cpp:4]: (error) Memory pointed to by 'p' is freed twice.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:4]: (error) Memory pointed to by 'p' is freed twice.\n", errout.str());
|
||||
|
||||
check(
|
||||
"void foo(char *p) {\n"
|
||||
" delete[] p;\n"
|
||||
" delete[] p;\n"
|
||||
"}", true);
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Memory pointed to by 'p' is freed twice.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (error) Memory pointed to by 'p' is freed twice.\n", errout.str());
|
||||
|
||||
check(
|
||||
"void foo(char *p, char *r) {\n"
|
||||
|
@ -822,7 +822,7 @@ private:
|
|||
" bar();\n"
|
||||
" delete[] p;\n"
|
||||
"}", true);
|
||||
ASSERT_EQUALS("[test.cpp:4]: (error) Memory pointed to by 'p' is freed twice.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:4]: (error) Memory pointed to by 'p' is freed twice.\n", errout.str());
|
||||
|
||||
check(
|
||||
"LineMarker::~LineMarker() {\n"
|
||||
|
@ -866,7 +866,7 @@ private:
|
|||
" delete a;\n"
|
||||
" return 0;\n"
|
||||
"}", true);
|
||||
TODO_ASSERT_EQUALS("", "[test.cpp:11]: (error) Memory pointed to by 'a' is freed twice.\n", errout.str());
|
||||
TODO_ASSERT_EQUALS("", "[test.cpp:8] -> [test.cpp:11]: (error) Memory pointed to by 'a' is freed twice.\n", errout.str());
|
||||
|
||||
check(
|
||||
"void foo(int y)\n"
|
||||
|
@ -956,7 +956,7 @@ private:
|
|||
" }\n"
|
||||
" free(p);\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.c:8]: (error) Memory pointed to by 'p' is freed twice.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.c:6] -> [test.c:8]: (error) Memory pointed to by 'p' is freed twice.\n", errout.str());
|
||||
|
||||
check(
|
||||
"void MyFunction()\n"
|
||||
|
@ -1068,7 +1068,7 @@ private:
|
|||
" x = (q == p);\n"
|
||||
" free(p);\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.c:4]: (error) Memory pointed to by 'p' is freed twice.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.c:2] -> [test.c:4]: (error) Memory pointed to by 'p' is freed twice.\n", errout.str());
|
||||
}
|
||||
|
||||
void doublefree6() { // #7685
|
||||
|
@ -1101,35 +1101,35 @@ private:
|
|||
" std::unique_ptr<int> x(i);\n"
|
||||
" delete i;\n"
|
||||
"}\n", true);
|
||||
ASSERT_EQUALS("[test.cpp:4]: (error) Memory pointed to by 'i' is freed twice.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (error) Memory pointed to by 'i' is freed twice.\n", errout.str());
|
||||
|
||||
check("void f() {\n"
|
||||
" int * i = new int;\n"
|
||||
" delete i;\n"
|
||||
" std::unique_ptr<int> x(i);\n"
|
||||
"}\n", true);
|
||||
ASSERT_EQUALS("[test.cpp:4]: (error) Memory pointed to by 'i' is freed twice.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (error) Memory pointed to by 'i' is freed twice.\n", errout.str());
|
||||
|
||||
check("void f() {\n"
|
||||
" int * i = new int;\n"
|
||||
" std::unique_ptr<int> x{i};\n"
|
||||
" delete i;\n"
|
||||
"}\n", true);
|
||||
ASSERT_EQUALS("[test.cpp:4]: (error) Memory pointed to by 'i' is freed twice.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (error) Memory pointed to by 'i' is freed twice.\n", errout.str());
|
||||
|
||||
check("void f() {\n"
|
||||
" int * i = new int;\n"
|
||||
" std::shared_ptr<int> x(i);\n"
|
||||
" delete i;\n"
|
||||
"}\n", true);
|
||||
ASSERT_EQUALS("[test.cpp:4]: (error) Memory pointed to by 'i' is freed twice.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (error) Memory pointed to by 'i' is freed twice.\n", errout.str());
|
||||
|
||||
check("void f() {\n"
|
||||
" int * i = new int;\n"
|
||||
" std::shared_ptr<int> x{i};\n"
|
||||
" delete i;\n"
|
||||
"}\n", true);
|
||||
ASSERT_EQUALS("[test.cpp:4]: (error) Memory pointed to by 'i' is freed twice.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (error) Memory pointed to by 'i' is freed twice.\n", errout.str());
|
||||
|
||||
// Check for use-after-free FP
|
||||
check("void f() {\n"
|
||||
|
@ -1144,7 +1144,7 @@ private:
|
|||
" std::unique_ptr<int[]> x(i);\n"
|
||||
" delete i;\n"
|
||||
"}\n", true);
|
||||
ASSERT_EQUALS("[test.cpp:4]: (error) Memory pointed to by 'i' is freed twice.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (error) Memory pointed to by 'i' is freed twice.\n", errout.str());
|
||||
}
|
||||
|
||||
void doublefree9() {
|
||||
|
@ -1477,13 +1477,13 @@ private:
|
|||
" FILE*f=fopen(fname,a);\n"
|
||||
" free(f);\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.c:3]: (error) Mismatching allocation and deallocation: f\n", errout.str());
|
||||
ASSERT_EQUALS("[test.c:2] -> [test.c:3]: (error) Mismatching allocation and deallocation: f\n", errout.str());
|
||||
|
||||
check("void f() {\n"
|
||||
" FILE*f=fopen(fname,a);\n"
|
||||
" free((void*)f);\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.c:3]: (error) Mismatching allocation and deallocation: f\n", errout.str());
|
||||
ASSERT_EQUALS("[test.c:2] -> [test.c:3]: (error) Mismatching allocation and deallocation: f\n", errout.str());
|
||||
|
||||
check("void f() {\n"
|
||||
" char *cPtr = new char[100];\n"
|
||||
|
@ -1493,13 +1493,13 @@ private:
|
|||
" cPtr = new char[100];\n"
|
||||
" delete cPtr;\n"
|
||||
"}", true);
|
||||
ASSERT_EQUALS("[test.cpp:7]: (error) Mismatching allocation and deallocation: cPtr\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:6] -> [test.cpp:7]: (error) Mismatching allocation and deallocation: cPtr\n", errout.str());
|
||||
|
||||
check("void f() {\n"
|
||||
" char *cPtr = new char[100];\n"
|
||||
" free(cPtr);\n"
|
||||
"}", true);
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Mismatching allocation and deallocation: cPtr\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (error) Mismatching allocation and deallocation: cPtr\n", errout.str());
|
||||
|
||||
check("void f() {\n"
|
||||
" char *cPtr = new (buf) char[100];\n"
|
||||
|
@ -1510,21 +1510,21 @@ private:
|
|||
" int * i = new int[1];\n"
|
||||
" std::unique_ptr<int> x(i);\n"
|
||||
"}\n", true);
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Mismatching allocation and deallocation: i\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (error) Mismatching allocation and deallocation: i\n", errout.str());
|
||||
|
||||
check("void f() {\n"
|
||||
" int * i = new int;\n"
|
||||
" std::unique_ptr<int[]> x(i);\n"
|
||||
"}\n", true);
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Mismatching allocation and deallocation: i\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (error) Mismatching allocation and deallocation: i\n", errout.str());
|
||||
|
||||
check("void f() {\n"
|
||||
" void* a = malloc(1);\n"
|
||||
" void* b = freopen(f, p, a);\n"
|
||||
" free(b);\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.c:3]: (error) Mismatching allocation and deallocation: a\n"
|
||||
"[test.c:4]: (error) Mismatching allocation and deallocation: b\n", errout.str());
|
||||
ASSERT_EQUALS("[test.c:2] -> [test.c:3]: (error) Mismatching allocation and deallocation: a\n"
|
||||
"[test.c:3] -> [test.c:4]: (error) Mismatching allocation and deallocation: b\n", errout.str());
|
||||
|
||||
check("void f() {\n"
|
||||
" void* a;\n"
|
||||
|
@ -1538,8 +1538,8 @@ private:
|
|||
" int * j = realloc(i, 2 * sizeof(int));\n"
|
||||
" delete[] j;\n"
|
||||
"}", true);
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Mismatching allocation and deallocation: i\n"
|
||||
"[test.cpp:4]: (error) Mismatching allocation and deallocation: j\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (error) Mismatching allocation and deallocation: i\n"
|
||||
"[test.cpp:3] -> [test.cpp:4]: (error) Mismatching allocation and deallocation: j\n", errout.str());
|
||||
}
|
||||
|
||||
void smartPointerDeleter() {
|
||||
|
@ -1547,7 +1547,7 @@ private:
|
|||
" FILE*f=fopen(fname,a);\n"
|
||||
" std::unique_ptr<FILE> fp{f};\n"
|
||||
"}", true);
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Mismatching allocation and deallocation: f\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (error) Mismatching allocation and deallocation: f\n", errout.str());
|
||||
|
||||
check("void f() {\n"
|
||||
" FILE*f=fopen(fname,a);\n"
|
||||
|
@ -1600,13 +1600,13 @@ private:
|
|||
" FILE*f=fopen(fname,a);\n"
|
||||
" std::shared_ptr<FILE> fp{f, [](FILE* x) { free(f); }};\n"
|
||||
"}", true);
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Mismatching allocation and deallocation: f\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (error) Mismatching allocation and deallocation: f\n", errout.str());
|
||||
|
||||
check("void f() {\n"
|
||||
" FILE*f=fopen(fname,a);\n"
|
||||
" std::shared_ptr<FILE> fp{f, [](FILE* x) {}};\n"
|
||||
"}", true);
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Mismatching allocation and deallocation: f\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (error) Mismatching allocation and deallocation: f\n", errout.str());
|
||||
|
||||
check("class C;\n"
|
||||
"void f() {\n"
|
||||
|
|
Loading…
Reference in New Issue