Fix #4045: memory leak not reported after usage of " + p[]"
This commit is contained in:
parent
927a6e4794
commit
327db15284
|
@ -934,24 +934,37 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
|
||||||
else {
|
else {
|
||||||
// is the pointer in rhs?
|
// is the pointer in rhs?
|
||||||
bool rhs = false;
|
bool rhs = false;
|
||||||
|
bool trailingSemicolon = false;
|
||||||
|
bool used = false;
|
||||||
for (const Token *tok2 = tok->next(); tok2; tok2 = tok2->next()) {
|
for (const Token *tok2 = tok->next(); tok2; tok2 = tok2->next()) {
|
||||||
if (tok2->str() == ";") {
|
if (tok2->str() == ";") {
|
||||||
|
trailingSemicolon = true;
|
||||||
if (rhs)
|
if (rhs)
|
||||||
tok = tok2;
|
tok = tok2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Token::Match(tok2, "[=+(,] %varid%", varid)) {
|
if (!used) {
|
||||||
if (!rhs && Token::Match(tok2, "[(,]")) {
|
if (Token::Match(tok2, "[=+(,] %varid%", varid)) {
|
||||||
addtoken(&rettail, tok, "use");
|
if (!rhs && Token::Match(tok2, "[(,]")) {
|
||||||
addtoken(&rettail, tok, ";");
|
used = true;
|
||||||
|
addtoken(&rettail, tok, "use");
|
||||||
|
addtoken(&rettail, tok, ";");
|
||||||
|
}
|
||||||
|
rhs = true;
|
||||||
}
|
}
|
||||||
rhs = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rhs)
|
if (!used) {
|
||||||
addtoken(&rettail, tok, "assign");
|
if (!rhs)
|
||||||
|
addtoken(&rettail, tok, "assign");
|
||||||
|
else {
|
||||||
|
addtoken(&rettail, tok, "use_");
|
||||||
|
if (trailingSemicolon)
|
||||||
|
addtoken(&rettail, tok, ";");
|
||||||
|
}
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1250,12 +1263,15 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
|
||||||
return rethead;
|
return rethead;
|
||||||
}
|
}
|
||||||
if (Token::Match(tok, "[)=] %varid% [+;)]", varid) ||
|
if (Token::Match(tok, "[)=] %varid% [+;)]", varid) ||
|
||||||
Token::Match(tok, "%var% + %varid%", varid) ||
|
(Token::Match(tok, "%var% + %varid%", varid) &&
|
||||||
|
tok->strAt(3) != "[" &&
|
||||||
|
tok->strAt(3) != ".") ||
|
||||||
Token::Match(tok, "<< %varid% ;", varid) ||
|
Token::Match(tok, "<< %varid% ;", varid) ||
|
||||||
Token::Match(tok, "= strcpy|strcat|memmove|memcpy ( %varid% ,", varid) ||
|
Token::Match(tok, "= strcpy|strcat|memmove|memcpy ( %varid% ,", varid) ||
|
||||||
Token::Match(tok, "[;{}] %var% [ %varid% ]", varid)) {
|
Token::Match(tok, "[;{}] %var% [ %varid% ]", varid)) {
|
||||||
addtoken(&rettail, tok, "use");
|
addtoken(&rettail, tok, "use");
|
||||||
} else if (Token::Match(tok->previous(), ";|{|}|=|(|,|%op% %varid% [", varid)) {
|
} else if (Token::Match(tok->previous(), ";|{|}|=|(|,|%op% %varid% [", varid) ||
|
||||||
|
Token::Match(tok->previous(), ";|{|}|=|(|,|%op% %varid% .", varid)) {
|
||||||
// warning is written for "dealloc ; use_ ;".
|
// warning is written for "dealloc ; use_ ;".
|
||||||
// but this use doesn't affect the leak-checking
|
// but this use doesn't affect the leak-checking
|
||||||
addtoken(&rettail, tok, "use_");
|
addtoken(&rettail, tok, "use_");
|
||||||
|
@ -1828,11 +1844,36 @@ void CheckMemoryLeakInFunction::simplifycode(Token *tok) const
|
||||||
}
|
}
|
||||||
|
|
||||||
// use use => use
|
// use use => use
|
||||||
if (Token::simpleMatch(tok2, "use use")) {
|
while (Token::simpleMatch(tok2, "use use")) {
|
||||||
tok2->deleteNext();
|
tok2->deleteNext();
|
||||||
done = false;
|
done = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// use use_ => use
|
||||||
|
if (Token::simpleMatch(tok2, "use use_")) {
|
||||||
|
tok2->deleteNext();
|
||||||
|
done = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// use_ use => use
|
||||||
|
if (Token::simpleMatch(tok2, "use_ use")) {
|
||||||
|
tok2->deleteThis();
|
||||||
|
done = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// use & use => use
|
||||||
|
while (Token::simpleMatch(tok2, "use & use")) {
|
||||||
|
tok2->deleteNext(2);
|
||||||
|
done = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// & use use => use
|
||||||
|
while (Token::simpleMatch(tok2, "& use use")) {
|
||||||
|
tok2->deleteThis();
|
||||||
|
tok2->deleteThis();
|
||||||
|
done = false;
|
||||||
|
}
|
||||||
|
|
||||||
// use; if| use; => use;
|
// use; if| use; => use;
|
||||||
while (Token::Match(tok2, "[;{}] use ; if| use ;")) {
|
while (Token::Match(tok2, "[;{}] use ; if| use ;")) {
|
||||||
Token *t = tok2->tokAt(2);
|
Token *t = tok2->tokAt(2);
|
||||||
|
|
|
@ -276,6 +276,7 @@ public:
|
||||||
* - "use" : unknown usage -> bail out checking of this execution path
|
* - "use" : unknown usage -> bail out checking of this execution path
|
||||||
* - "&use" : the address of the variable is taken
|
* - "&use" : the address of the variable is taken
|
||||||
* - "::use" : calling member function of class
|
* - "::use" : calling member function of class
|
||||||
|
* - "use_" : content of variable is accessed (used to warn access after dealloc)
|
||||||
*/
|
*/
|
||||||
Token *getcode(const Token *tok, std::list<const Token *> callstack, const unsigned int varid, AllocType &alloctype, AllocType &dealloctype, bool classmember, unsigned int sz);
|
Token *getcode(const Token *tok, std::list<const Token *> callstack, const unsigned int varid, AllocType &alloctype, AllocType &dealloctype, bool classmember, unsigned int sz);
|
||||||
|
|
||||||
|
|
|
@ -500,11 +500,18 @@ private:
|
||||||
ASSERT_EQUALS(";;use;;", getcode("char *s; x = {1,s};", "s"));
|
ASSERT_EQUALS(";;use;;", getcode("char *s; x = {1,s};", "s"));
|
||||||
ASSERT_EQUALS(";{};;alloc;;use;", getcode("struct Foo { }; Foo *p; p = malloc(10); const Foo *q; q = p;", "p"));
|
ASSERT_EQUALS(";{};;alloc;;use;", getcode("struct Foo { }; Foo *p; p = malloc(10); const Foo *q; q = p;", "p"));
|
||||||
ASSERT_EQUALS(";;alloc;use;", getcode("Fred *fred; p.setFred(fred = new Fred);", "fred"));
|
ASSERT_EQUALS(";;alloc;use;", getcode("Fred *fred; p.setFred(fred = new Fred);", "fred"));
|
||||||
ASSERT_EQUALS(";;use;", getcode("struct AB *ab; f(ab->a);", "ab"));
|
ASSERT_EQUALS(";;useuse_;", getcode("struct AB *ab; f(ab->a);", "ab"));
|
||||||
ASSERT_EQUALS(";;use;", getcode("struct AB *ab; ab = pop(ab);", "ab"));
|
ASSERT_EQUALS(";;use;", getcode("struct AB *ab; ab = pop(ab);", "ab"));
|
||||||
|
|
||||||
// non-use..
|
// non-use..
|
||||||
ASSERT_EQUALS(";;", getcode("char *s; s = s + 1;", "s"));
|
ASSERT_EQUALS(";;use_;", getcode("char *s; c = x + s[0];","s"));
|
||||||
|
ASSERT_EQUALS(";;use_;", getcode("char *s; c = s[0] + x;","s"));
|
||||||
|
ASSERT_EQUALS(";;use_;", getcode("type *c; y = x + c->y;","c"));
|
||||||
|
ASSERT_EQUALS(";;use_;", getcode("type *c; y = c->y + x;","c"));
|
||||||
|
ASSERT_EQUALS(";;use_;", getcode("char *s; s = s + 1;", "s"));
|
||||||
|
|
||||||
|
// use reference
|
||||||
|
ASSERT_EQUALS(";;callfunc&use;", getcode("struct AB *ab; f(&ab);", "ab"));
|
||||||
|
|
||||||
// reference
|
// reference
|
||||||
ASSERT_EQUALS(";", getcode("char *p; char * & ref = p; p = malloc(10);", "p"));
|
ASSERT_EQUALS(";", getcode("char *p; char * & ref = p; p = malloc(10);", "p"));
|
||||||
|
@ -664,6 +671,10 @@ private:
|
||||||
|
|
||||||
// use..
|
// use..
|
||||||
ASSERT_EQUALS("; use ; }", simplifycode("; use use ; }"));
|
ASSERT_EQUALS("; use ; }", simplifycode("; use use ; }"));
|
||||||
|
ASSERT_EQUALS("; use ; }", simplifycode("; use use_ ; }"));
|
||||||
|
ASSERT_EQUALS("; use ; }", simplifycode("; use_ use ; }"));
|
||||||
|
ASSERT_EQUALS("; use ; }", simplifycode("; &use use ; }"));
|
||||||
|
ASSERT_EQUALS("; use ; }", simplifycode("; use &use ; }"));
|
||||||
ASSERT_EQUALS("; alloc ; dealloc ; }", simplifycode("; alloc ; use ; use ; if use ; dealloc ; }"));
|
ASSERT_EQUALS("; alloc ; dealloc ; }", simplifycode("; alloc ; use ; use ; if use ; dealloc ; }"));
|
||||||
|
|
||||||
// if, else..
|
// if, else..
|
||||||
|
|
Loading…
Reference in New Issue