Fixed #5522 (CheckLeakAutoVar: Don't treat 'x==p' as dereference of p)
This commit is contained in:
parent
be755af762
commit
4b903a838f
|
@ -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());
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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"
|
||||||
|
|
Loading…
Reference in New Issue