Fix #4045: memory leak not reported after usage of " + p[]"

This commit is contained in:
Frank Zingsheim 2012-12-09 08:59:21 +01:00
parent 927a6e4794
commit 327db15284
3 changed files with 65 additions and 12 deletions

View File

@ -934,24 +934,37 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
else {
// is the pointer in rhs?
bool rhs = false;
bool trailingSemicolon = false;
bool used = false;
for (const Token *tok2 = tok->next(); tok2; tok2 = tok2->next()) {
if (tok2->str() == ";") {
trailingSemicolon = true;
if (rhs)
tok = tok2;
break;
}
if (Token::Match(tok2, "[=+(,] %varid%", varid)) {
if (!rhs && Token::Match(tok2, "[(,]")) {
addtoken(&rettail, tok, "use");
addtoken(&rettail, tok, ";");
if (!used) {
if (Token::Match(tok2, "[=+(,] %varid%", varid)) {
if (!rhs && Token::Match(tok2, "[(,]")) {
used = true;
addtoken(&rettail, tok, "use");
addtoken(&rettail, tok, ";");
}
rhs = true;
}
rhs = true;
}
}
if (!rhs)
addtoken(&rettail, tok, "assign");
if (!used) {
if (!rhs)
addtoken(&rettail, tok, "assign");
else {
addtoken(&rettail, tok, "use_");
if (trailingSemicolon)
addtoken(&rettail, tok, ";");
}
}
continue;
}
}
@ -1250,12 +1263,15 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
return rethead;
}
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, "= strcpy|strcat|memmove|memcpy ( %varid% ,", varid) ||
Token::Match(tok, "[;{}] %var% [ %varid% ]", varid)) {
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_ ;".
// but this use doesn't affect the leak-checking
addtoken(&rettail, tok, "use_");
@ -1828,11 +1844,36 @@ void CheckMemoryLeakInFunction::simplifycode(Token *tok) const
}
// use use => use
if (Token::simpleMatch(tok2, "use use")) {
while (Token::simpleMatch(tok2, "use use")) {
tok2->deleteNext();
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;
while (Token::Match(tok2, "[;{}] use ; if| use ;")) {
Token *t = tok2->tokAt(2);

View File

@ -276,6 +276,7 @@ public:
* - "use" : unknown usage -> bail out checking of this execution path
* - "&use" : the address of the variable is taken
* - "::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);

View File

@ -500,11 +500,18 @@ private:
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("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"));
// 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
ASSERT_EQUALS(";", getcode("char *p; char * & ref = p; p = malloc(10);", "p"));
@ -664,6 +671,10 @@ private:
// 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 ; }"));
// if, else..