Fixed #5522 (CheckLeakAutoVar: Don't treat 'x==p' as dereference of p)

This commit is contained in:
Daniel Marjamäki 2016-05-26 19:21:45 +02:00
parent be755af762
commit 4b903a838f
3 changed files with 15 additions and 1 deletions

View File

@ -22,6 +22,7 @@
#include "checkleakautovar.h" #include "checkleakautovar.h"
#include "checkmemoryleak.h" // <- CheckMemoryLeak::memoryLeak #include "checkmemoryleak.h" // <- CheckMemoryLeak::memoryLeak
#include "checknullpointer.h" // <- CheckNullPointer::isPointerDeRef
#include "tokenize.h" #include "tokenize.h"
#include "symboldatabase.h" #include "symboldatabase.h"
#include "astutils.h" #include "astutils.h"
@ -196,7 +197,8 @@ void CheckLeakAutoVar::checkScope(const Token * const startToken,
if (tok->varId() > 0) { if (tok->varId() > 0) {
const std::map<unsigned int, VarInfo::AllocInfo>::const_iterator var = alloctype.find(tok->varId()); const std::map<unsigned int, VarInfo::AllocInfo>::const_iterator var = alloctype.find(tok->varId());
if (var != alloctype.end()) { if (var != alloctype.end()) {
if (var->second.status == VarInfo::DEALLOC && tok->strAt(-1) != "&" && (!Token::Match(tok, "%name% =") || tok->strAt(-1) == "*")) { bool unknown = false;
if (var->second.status == VarInfo::DEALLOC && CheckNullPointer::isPointerDeRef(tok,unknown) && !unknown) {
deallocUseError(tok, tok->str()); deallocUseError(tok, tok->str());
} else if (Token::simpleMatch(tok->tokAt(-2), "= &")) { } else if (Token::simpleMatch(tok->tokAt(-2), "= &")) {
varInfo->erase(tok->varId()); varInfo->erase(tok->varId());

View File

@ -162,6 +162,8 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown)
const Token* parent = tok->astParent(); const Token* parent = tok->astParent();
if (!parent) if (!parent)
return false; return false;
if (parent->str() == "." && parent->astOperand2() == tok)
return isPointerDeRef(parent, unknown);
const bool firstOperand = parent->astOperand1() == tok; const bool firstOperand = parent->astOperand1() == tok;
while (parent->str() == "(" && (parent->astOperand2() == nullptr && parent->strAt(1) != ")")) { // Skip over casts while (parent->str() == "(" && (parent->astOperand2() == nullptr && parent->strAt(1) != ")")) { // Skip over casts
parent = parent->astParent(); parent = parent->astParent();

View File

@ -65,6 +65,7 @@ private:
TEST_CASE(doublefree2); TEST_CASE(doublefree2);
TEST_CASE(doublefree3); // #4914 TEST_CASE(doublefree3); // #4914
TEST_CASE(doublefree4); // #5451 - FP when exit is called TEST_CASE(doublefree4); // #5451 - FP when exit is called
TEST_CASE(doublefree5); // #5522
// exit // exit
TEST_CASE(exit1); TEST_CASE(exit1);
@ -812,6 +813,15 @@ private:
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void doublefree5() { // #5522
check("void f(char *p) {\n"
" free(p);\n"
" x = (q == p);\n"
" free(p);\n"
"}");
ASSERT_EQUALS("[test.c:4]: (error) Memory pointed to by 'p' is freed twice.\n", errout.str());
}
void exit1() { void exit1() {
check("void f() {\n" check("void f() {\n"
" char *p = malloc(10);\n" " char *p = malloc(10);\n"