From 87d3ed91abfd534aa850ade712330777061aeaed Mon Sep 17 00:00:00 2001 From: PKEuS Date: Wed, 18 Nov 2015 22:09:27 +0100 Subject: [PATCH] Refactorization: - Improved and cleaned up CheckMemoryLeak::functionReturnType() - Cleaned up whitelist from functions declared as in std.cfg --- lib/checkmemoryleak.cpp | 69 ++++++++++++++--------------------------- test/testmemleak.cpp | 12 +------ 2 files changed, 25 insertions(+), 56 deletions(-) diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index 391bcd40c..a55787d14 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -58,37 +58,24 @@ static unsigned int countParameters(const Token *tok) /** List of functions that can be ignored when searching for memory leaks. * These functions don't take the address of the given pointer - * This list needs to be alphabetically sorted so we can run bsearch on it. * This list contains function names with const parameters e.g.: atof(const char *) - * Reference: http://www.aquaphoenix.com/ref/gnu_c_library/libc_492.html#SEC492 + * TODO: This list should be replaced by in .cfg files. */ static const std::set call_func_white_list = make_container < std::set > () - << "_open" << "_wopen" << "access" << "adjtime" << "asctime" << "asctime_r" << "asprintf" << "assert" - << "atof" << "atoi" << "atol" << "chdir" << "chmod" << "chown" - << "clearerr" << "creat" << "ctime" << "ctime_r" << "execl" << "execle" - << "execlp" << "execv" << "execve" << "fchmod" << "fclose" << "fcntl" - << "fdatasync" << "feof" << "ferror" << "fflush" << "fgetc" << "fgetpos" << "fgets" - << "flock" << "fmemopen" << "fnmatch" << "fopen" << "fopencookie" << "for" << "fprintf" << "fputc" << "fputs" << "fread" << "free" - << "freopen" << "fscanf" << "fseek" << "fseeko" << "fsetpos" << "fstat" << "fsync" << "ftell" << "ftello" - << "ftruncate" << "fwrite" << "getc" << "getenv" << "getgrnam" << "gethostbyaddr" << "gethostbyname" << "getnetbyname" - << "getopt" << "getopt_long" << "getprotobyname" << "getpwnam" << "gets" << "getservbyname" << "getservbyport" - << "glob" << "gmtime" << "gmtime_r" << "if" << "index" << "inet_addr" << "inet_aton" << "inet_network" << "initgroups" << "ioctl" - << "link" << "localtime" << "localtime_r" - << "lockf" << "lseek" << "lstat" << "mblen" << "mbstowcs" << "mbtowc" << "memchr" << "memcmp" << "memcpy" << "memmove" << "memset" - << "mkdir" << "mkfifo" << "mknod" << "mkstemp" + << "_open" << "_wopen" << "access" << "adjtime" << "asctime_r" << "asprintf" << "chdir" << "chmod" << "chown" + << "creat" << "ctime_r" << "execl" << "execle" << "execlp" << "execv" << "execve" << "fchmod" << "fcntl" + << "fdatasync" << "fclose" << "flock" << "fmemopen" << "fnmatch" << "fopen" << "fopencookie" << "for" << "free" + << "freopen"<< "fseeko" << "fstat" << "fsync" << "ftello" << "ftruncate" << "getgrnam" << "gethostbyaddr" << "gethostbyname" + << "getnetbyname" << "getopt" << "getopt_long" << "getprotobyname" << "getpwnam" << "getservbyname" << "getservbyport" + << "glob" << "gmtime" << "gmtime_r" << "if" << "index" << "inet_addr" << "inet_aton" << "inet_network" << "initgroups" + << "ioctl" << "link" << "localtime_r" << "lockf" << "lseek" << "lstat" << "mkdir" << "mkfifo" << "mknod" << "mkstemp" << "obstack_printf" << "obstack_vprintf" << "open" << "opendir" << "parse_printf_format" << "pathconf" - << "perror" << "popen" << "posix_fadvise" << "posix_fallocate" << "pread" - << "printf" << "psignal" << "puts" << "pwrite" << "qsort" << "read" << "readahead" << "readdir" << "readdir_r" - << "readlink" << "readv" - << "realloc" << "regcomp" << "remove" << "rename" << "return" << "rewind" << "rewinddir" << "rindex" - << "rmdir" << "scandir" << "scanf" << "seekdir" - << "setbuf" << "setbuffer" << "sethostname" << "setlinebuf" << "setlocale" << "setvbuf" << "sizeof" << "snprintf" << "sprintf" << "sscanf" - << "stat" << "stpcpy" << "strcasecmp" << "strcat" << "strchr" << "strcmp" << "strcoll" - << "strcpy" << "strcspn" << "strdup" << "stricmp" << "strlen" << "strncasecmp" << "strncat" << "strncmp" - << "strncpy" << "strpbrk" << "strrchr" << "strspn" << "strstr" << "strtod" << "strtok" << "strtol" << "strtoul" << "strxfrm" << "switch" - << "symlink" << "sync_file_range" << "system" << "telldir" << "tempnam" << "time" << "typeid" << "unlink" - << "utime" << "utimes" << "vasprintf" << "vfprintf" << "vfscanf" << "vprintf" - << "vscanf" << "vsnprintf" << "vsprintf" << "vsscanf" << "while" << "wordexp" << "write" << "writev"; + << "perror" << "popen" << "posix_fadvise" << "posix_fallocate" << "pread" << "psignal" << "pwrite" << "read" << "readahead" + << "readdir" << "readdir_r" << "readlink" << "readv" << "realloc" << "regcomp" << "return" << "rewinddir" << "rindex" + << "rmdir" << "scandir" << "seekdir" << "setbuffer" << "sethostname" << "setlinebuf" << "sizeof" << "strdup" + << "stat" << "stpcpy" << "strcasecmp" << "stricmp" << "strncasecmp" << "switch" + << "symlink" << "sync_file_range" << "telldir" << "tempnam" << "time" << "typeid" << "unlink" + << "utime" << "utimes" << "vasprintf" << "while" << "wordexp" << "write" << "writev"; //--------------------------------------------------------------------------- @@ -363,24 +350,19 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::functionReturnType(const Function* f // Get return pointer.. unsigned int varid = 0; - unsigned int indentlevel = 0; for (const Token *tok2 = func->functionScope->classStart; tok2 != func->functionScope->classEnd; tok2 = tok2->next()) { - if (tok2->str() == "{") - ++indentlevel; - else if (tok2->str() == "}") { - if (indentlevel <= 1) - return No; - --indentlevel; - } - if (Token::Match(tok2, "return %name% ;")) { - if (indentlevel != 1) - return No; - varid = tok2->next()->varId(); - break; - } else if (tok2->str() == "return") { + if (tok2->str() == "return") { AllocType allocType = getAllocationType(tok2->next(), 0, callstack); if (allocType != No) return allocType; + + if (tok2->scope() != func->functionScope || !tok2->astOperand1()) + return No; + const Token* tok = tok2->astOperand1(); + if (Token::Match(tok, ".|::")) + tok = tok->astOperand2(); + varid = tok->varId(); + break; } } @@ -404,10 +386,7 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::functionReturnType(const Function* f if (Token::Match(tok, "= %varid% ;", varid)) { return No; } - if (Token::Match(tok, "static %type% * %varid% [;{}=]", varid)) { - return No; - } - if (Token::Match(tok, "[(,] %varid% [,)]", varid)) { + if (!tokenizer->isC() && Token::Match(tok, "[(,] %varid% [,)]", varid)) { return No; } if (Token::Match(tok, "[(,] & %varid% [.,)]", varid)) { diff --git a/test/testmemleak.cpp b/test/testmemleak.cpp index b5f449199..c8ae2c4a2 100644 --- a/test/testmemleak.cpp +++ b/test/testmemleak.cpp @@ -6175,19 +6175,9 @@ private: settings.standards.posix = true; settings.addEnabled("warning"); + LOAD_LIB_2(settings.library, "std.cfg"); LOAD_LIB_2(settings.library, "gtk.cfg"); - // Add some test allocation functions to the library. - // When not run as a unit test, these are read from - // an XML file (e.g. cfg/posix.cfg). - int id = 0; - while (!settings.library.ismemory(++id)) - continue; - settings.library.setalloc("malloc", id); - settings.library.setalloc("calloc", id); - settings.library.setalloc("strdup", id); - - // pass allocated memory to function.. TEST_CASE(functionParameter);