LCOV - code coverage report
Current view: top level - lib - checknullpointer.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 879 909 96.7 %
Date: 2013-03-30 Functions: 29 29 100.0 %
Branches: 1604 2402 66.8 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Cppcheck - A tool for static C/C++ code analysis
       3                 :            :  * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team.
       4                 :            :  *
       5                 :            :  * This program is free software: you can redistribute it and/or modify
       6                 :            :  * it under the terms of the GNU General Public License as published by
       7                 :            :  * the Free Software Foundation, either version 3 of the License, or
       8                 :            :  * (at your option) any later version.
       9                 :            :  *
      10                 :            :  * This program is distributed in the hope that it will be useful,
      11                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      12                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13                 :            :  * GNU General Public License for more details.
      14                 :            :  *
      15                 :            :  * You should have received a copy of the GNU General Public License
      16                 :            :  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
      17                 :            :  */
      18                 :            : 
      19                 :            : 
      20                 :            : //---------------------------------------------------------------------------
      21                 :            : #include "checknullpointer.h"
      22                 :            : #include "executionpath.h"
      23                 :            : #include "mathlib.h"
      24                 :            : #include "symboldatabase.h"
      25                 :            : #include <cctype>
      26                 :            : //---------------------------------------------------------------------------
      27                 :            : 
      28                 :            : // Register this check class (by creating a static instance of it)
      29                 :            : namespace {
      30                 :         45 :     CheckNullPointer instance;
      31                 :            : }
      32                 :            : 
      33                 :            : //---------------------------------------------------------------------------
      34                 :            : 
      35                 :            : /**
      36                 :            :  * @brief parse a function call and extract information about variable usage
      37                 :            :  * @param tok first token
      38                 :            :  * @param var variables that the function read / write.
      39                 :            :  * @param value 0 => invalid with null pointers as parameter.
      40                 :            :  *              1-.. => invalid with uninitialized data.
      41                 :            :  */
      42                 :      25321 : void CheckNullPointer::parseFunctionCall(const Token &tok, std::list<const Token *> &var, unsigned char value)
      43                 :            : {
      44                 :            :     // standard functions that dereference first parameter..
      45 [ +  + ][ +  - ]:      25321 :     static std::set<std::string> functionNames1_all;
         [ +  - ][ #  # ]
      46 [ +  + ][ +  - ]:      25321 :     static std::set<std::string> functionNames1_nullptr;
         [ +  - ][ #  # ]
      47 [ +  + ][ +  - ]:      25321 :     static std::set<std::string> functionNames1_uninit;
         [ +  - ][ #  # ]
      48         [ +  + ]:      25321 :     if (functionNames1_all.empty()) {
      49                 :            :         // cstdlib
      50 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("atoi");
                 [ +  - ]
      51 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("atof");
                 [ +  - ]
      52 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("atol");
                 [ +  - ]
      53 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("qsort");
                 [ +  - ]
      54 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("strtof");
                 [ +  - ]
      55 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("strtod");
                 [ +  - ]
      56 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("strtol");
                 [ +  - ]
      57 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("strtoul");
                 [ +  - ]
      58 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("strtold");
                 [ +  - ]
      59 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("strtoll");
                 [ +  - ]
      60 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("strtoull");
                 [ +  - ]
      61 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("wcstof");
                 [ +  - ]
      62 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("wcstod");
                 [ +  - ]
      63 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("wcstol");
                 [ +  - ]
      64 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("wcstoul");
                 [ +  - ]
      65 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("wcstold");
                 [ +  - ]
      66 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("wcstoll");
                 [ +  - ]
      67 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("wcstoull");
                 [ +  - ]
      68                 :            :         // cstring
      69 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("memchr");
                 [ +  - ]
      70 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("memcmp");
                 [ +  - ]
      71 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("strcat");
                 [ +  - ]
      72 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("strncat");
                 [ +  - ]
      73 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("strcoll");
                 [ +  - ]
      74 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("strchr");
                 [ +  - ]
      75 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("strrchr");
                 [ +  - ]
      76 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("strcmp");
                 [ +  - ]
      77 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("strncmp");
                 [ +  - ]
      78 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("strcspn");
                 [ +  - ]
      79 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("strdup");
                 [ +  - ]
      80 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("strndup");
                 [ +  - ]
      81 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("strpbrk");
                 [ +  - ]
      82 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("strlen");
                 [ +  - ]
      83 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("strspn");
                 [ +  - ]
      84 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("strstr");
                 [ +  - ]
      85 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("wcscat");
                 [ +  - ]
      86 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("wcsncat");
                 [ +  - ]
      87 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("wcscoll");
                 [ +  - ]
      88 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("wcschr");
                 [ +  - ]
      89 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("wcsrchr");
                 [ +  - ]
      90 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("wcscmp");
                 [ +  - ]
      91 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("wcsncmp");
                 [ +  - ]
      92 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("wcscspn");
                 [ +  - ]
      93 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("wcsdup");
                 [ +  - ]
      94 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("wcsndup");
                 [ +  - ]
      95 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("wcspbrk");
                 [ +  - ]
      96 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("wcslen");
                 [ +  - ]
      97 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("wcsspn");
                 [ +  - ]
      98 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("wcsstr");
                 [ +  - ]
      99                 :            :         // cstdio
     100 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("fclose");
                 [ +  - ]
     101 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("feof");
                 [ +  - ]
     102 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("fwrite");
                 [ +  - ]
     103 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("fseek");
                 [ +  - ]
     104 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("ftell");
                 [ +  - ]
     105 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("fputs");
                 [ +  - ]
     106 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("fputws");
                 [ +  - ]
     107 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("ferror");
                 [ +  - ]
     108 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("fgetc");
                 [ +  - ]
     109 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("fgetwc");
                 [ +  - ]
     110 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("fgetpos");
                 [ +  - ]
     111 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("fsetpos");
                 [ +  - ]
     112 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("freopen");
                 [ +  - ]
     113 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("fscanf");
                 [ +  - ]
     114 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("fprintf");
                 [ +  - ]
     115 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("fwscanf");
                 [ +  - ]
     116 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("fwprintf");
                 [ +  - ]
     117 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("fopen");
                 [ +  - ]
     118 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("rewind");
                 [ +  - ]
     119 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("printf");
                 [ +  - ]
     120 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("wprintf");
                 [ +  - ]
     121 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("scanf");
                 [ +  - ]
     122 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("wscanf");
                 [ +  - ]
     123 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("fscanf");
                 [ +  - ]
     124 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("sscanf");
                 [ +  - ]
     125 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("fwscanf");
                 [ +  - ]
     126 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("swscanf");
                 [ +  - ]
     127 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("setbuf");
                 [ +  - ]
     128 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("setvbuf");
                 [ +  - ]
     129 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("rename");
                 [ +  - ]
     130 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("remove");
                 [ +  - ]
     131 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("puts");
                 [ +  - ]
     132 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("getc");
                 [ +  - ]
     133 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("clearerr");
                 [ +  - ]
     134                 :            :         // ctime
     135 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("asctime");
                 [ +  - ]
     136 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("ctime");
                 [ +  - ]
     137 [ +  - ][ +  - ]:         45 :         functionNames1_all.insert("mktime");
                 [ +  - ]
     138                 :            : 
     139 [ +  - ][ +  - ]:         45 :         functionNames1_nullptr.insert("itoa");
                 [ +  - ]
     140 [ +  - ][ +  - ]:         45 :         functionNames1_nullptr.insert("memcpy");
                 [ +  - ]
     141 [ +  - ][ +  - ]:         45 :         functionNames1_nullptr.insert("memmove");
                 [ +  - ]
     142 [ +  - ][ +  - ]:         45 :         functionNames1_nullptr.insert("memset");
                 [ +  - ]
     143 [ +  - ][ +  - ]:         45 :         functionNames1_nullptr.insert("strcpy");
                 [ +  - ]
     144 [ +  - ][ +  - ]:         45 :         functionNames1_nullptr.insert("sprintf");
                 [ +  - ]
     145 [ +  - ][ +  - ]:         45 :         functionNames1_nullptr.insert("vsprintf");
                 [ +  - ]
     146 [ +  - ][ +  - ]:         45 :         functionNames1_nullptr.insert("vprintf");
                 [ +  - ]
     147 [ +  - ][ +  - ]:         45 :         functionNames1_nullptr.insert("fprintf");
                 [ +  - ]
     148 [ +  - ][ +  - ]:         45 :         functionNames1_nullptr.insert("vfprintf");
                 [ +  - ]
     149 [ +  - ][ +  - ]:         45 :         functionNames1_nullptr.insert("wcscpy");
                 [ +  - ]
     150 [ +  - ][ +  - ]:         45 :         functionNames1_nullptr.insert("swprintf");
                 [ +  - ]
     151 [ +  - ][ +  - ]:         45 :         functionNames1_nullptr.insert("vswprintf");
                 [ +  - ]
     152 [ +  - ][ +  - ]:         45 :         functionNames1_nullptr.insert("vwprintf");
                 [ +  - ]
     153 [ +  - ][ +  - ]:         45 :         functionNames1_nullptr.insert("fwprintf");
                 [ +  - ]
     154 [ +  - ][ +  - ]:         45 :         functionNames1_nullptr.insert("vfwprintf");
                 [ +  - ]
     155 [ +  - ][ +  - ]:         45 :         functionNames1_nullptr.insert("fread");
                 [ +  - ]
     156 [ +  - ][ +  - ]:         45 :         functionNames1_nullptr.insert("gets");
                 [ +  - ]
     157 [ +  - ][ +  - ]:         45 :         functionNames1_nullptr.insert("gmtime");
                 [ +  - ]
     158 [ +  - ][ +  - ]:         45 :         functionNames1_nullptr.insert("localtime");
                 [ +  - ]
     159 [ +  - ][ +  - ]:         45 :         functionNames1_nullptr.insert("strftime");
                 [ +  - ]
     160                 :            : 
     161 [ +  - ][ +  - ]:         45 :         functionNames1_uninit.insert("perror");
                 [ +  - ]
     162 [ +  - ][ +  - ]:         45 :         functionNames1_uninit.insert("fflush");
                 [ +  - ]
     163                 :            :     }
     164                 :            : 
     165                 :            :     // standard functions that dereference second parameter..
     166 [ +  + ][ +  - ]:      25321 :     static std::set<std::string> functionNames2_all;
         [ +  - ][ #  # ]
     167 [ +  + ][ +  - ]:      25321 :     static std::set<std::string> functionNames2_nullptr;
         [ +  - ][ #  # ]
     168         [ +  + ]:      25321 :     if (functionNames2_all.empty()) {
     169 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("mbstowcs");
                 [ +  - ]
     170 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("wcstombs");
                 [ +  - ]
     171 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("memcmp");
                 [ +  - ]
     172 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("memcpy");
                 [ +  - ]
     173 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("memmove");
                 [ +  - ]
     174 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("strcat");
                 [ +  - ]
     175 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("strncat");
                 [ +  - ]
     176 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("strcmp");
                 [ +  - ]
     177 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("strncmp");
                 [ +  - ]
     178 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("strcoll");
                 [ +  - ]
     179 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("strcpy");
                 [ +  - ]
     180 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("strcspn");
                 [ +  - ]
     181 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("strncpy");
                 [ +  - ]
     182 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("strpbrk");
                 [ +  - ]
     183 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("strspn");
                 [ +  - ]
     184 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("strstr");
                 [ +  - ]
     185 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("strxfrm");
                 [ +  - ]
     186 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("wcscat");
                 [ +  - ]
     187 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("wcsncat");
                 [ +  - ]
     188 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("wcscmp");
                 [ +  - ]
     189 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("wcsncmp");
                 [ +  - ]
     190 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("wcscoll");
                 [ +  - ]
     191 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("wcscpy");
                 [ +  - ]
     192 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("wcscspn");
                 [ +  - ]
     193 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("wcsncpy");
                 [ +  - ]
     194 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("wcspbrk");
                 [ +  - ]
     195 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("wcsspn");
                 [ +  - ]
     196 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("wcsstr");
                 [ +  - ]
     197 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("wcsxfrm");
                 [ +  - ]
     198 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("sprintf");
                 [ +  - ]
     199 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("fprintf");
                 [ +  - ]
     200 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("fscanf");
                 [ +  - ]
     201 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("sscanf");
                 [ +  - ]
     202 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("swprintf");
                 [ +  - ]
     203 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("fwprintf");
                 [ +  - ]
     204 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("fwscanf");
                 [ +  - ]
     205 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("swscanf");
                 [ +  - ]
     206 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("fputs");
                 [ +  - ]
     207 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("fputc");
                 [ +  - ]
     208 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("ungetc");
                 [ +  - ]
     209 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("fputws");
                 [ +  - ]
     210 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("fputwc");
                 [ +  - ]
     211 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("ungetwc");
                 [ +  - ]
     212 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("rename");
                 [ +  - ]
     213 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("putc");
                 [ +  - ]
     214 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("putwc");
                 [ +  - ]
     215 [ +  - ][ +  - ]:         45 :         functionNames2_all.insert("freopen");
                 [ +  - ]
     216                 :            : 
     217 [ +  - ][ +  - ]:         45 :         functionNames2_nullptr.insert("frexp");
                 [ +  - ]
     218 [ +  - ][ +  - ]:         45 :         functionNames2_nullptr.insert("modf");
                 [ +  - ]
     219 [ +  - ][ +  - ]:         45 :         functionNames2_nullptr.insert("fgetpos");
                 [ +  - ]
     220                 :            :     }
     221                 :            : 
     222 [ +  + ][ -  + ]:      25321 :     if (Token::Match(&tok, "%var% ( )") || !tok.tokAt(2))
                 [ +  + ]
     223                 :       3945 :         return;
     224                 :            : 
     225                 :      21376 :     const Token* firstParam = tok.tokAt(2);
     226                 :      21376 :     const Token* secondParam = firstParam->nextArgument();
     227                 :            : 
     228                 :            :     // 1st parameter..
     229 [ +  + ][ +  + ]:      37410 :     if ((Token::Match(firstParam, "%var% ,|)") && firstParam->varId() > 0) ||
           [ +  +  +  + ]
                 [ +  + ]
     230                 :      16034 :         (value == 0 && Token::Match(firstParam, "0 ,|)"))) {
     231         [ +  + ]:       5984 :         if (functionNames1_all.find(tok.str()) != functionNames1_all.end())
     232                 :        886 :             var.push_back(firstParam);
     233 [ +  + ][ +  + ]:       5098 :         else if (value == 0 && functionNames1_nullptr.find(tok.str()) != functionNames1_nullptr.end())
                 [ +  + ]
     234                 :        596 :             var.push_back(firstParam);
     235 [ +  + ][ +  + ]:       4502 :         else if (value != 0 && functionNames1_uninit.find(tok.str()) != functionNames1_uninit.end())
                 [ +  + ]
     236                 :          2 :             var.push_back(firstParam);
     237 [ +  + ][ +  + ]:       4500 :         else if (value == 0 && Token::Match(&tok, "snprintf|vsnprintf|fnprintf|vfnprintf") && secondParam && secondParam->str() != "0") // Only if length (second parameter) is not zero
         [ +  - ][ +  + ]
                 [ +  + ]
     238                 :         90 :             var.push_back(firstParam);
     239                 :            :     }
     240                 :            : 
     241                 :            :     // 2nd parameter..
     242 [ +  + ][ +  + ]:      21376 :     if (secondParam && ((value == 0 && secondParam->str() == "0") || (secondParam->varId() > 0))) {
         [ +  + ][ +  + ]
                 [ +  + ]
     243         [ +  + ]:       1869 :         if (functionNames2_all.find(tok.str()) != functionNames2_all.end())
     244                 :        423 :             var.push_back(secondParam);
     245 [ +  + ][ +  + ]:       1446 :         else if (value == 0 && functionNames2_nullptr.find(tok.str()) != functionNames2_nullptr.end())
                 [ +  + ]
     246                 :        180 :             var.push_back(secondParam);
     247                 :            :     }
     248                 :            : 
     249         [ +  + ]:      21376 :     if (Token::Match(&tok, "printf|sprintf|snprintf|fprintf|fnprintf|scanf|sscanf|fscanf|wprintf|swprintf|fwprintf|wscanf|swscanf|fwscanf")) {
     250                 :       2792 :         const Token* argListTok = 0; // Points to first va_list argument
     251                 :       2792 :         std::string formatString;
     252         [ +  - ]:       2792 :         bool scan = Token::Match(&tok, "scanf|sscanf|fscanf|wscanf|swscanf|fwscanf");
     253                 :            : 
     254 [ +  - ][ +  + ]:       2792 :         if (Token::Match(&tok, "printf|scanf|wprintf|wscanf ( %str%")) {
     255 [ +  - ][ +  - ]:       1712 :             formatString = firstParam->strValue();
                 [ +  - ]
     256                 :       1712 :             argListTok = secondParam;
     257 [ +  - ][ +  + ]:       1080 :         } else if (Token::Match(&tok, "sprintf|fprintf|sscanf|fscanf|fwprintf|fwscanf|swscanf")) {
     258                 :        900 :             const Token* formatStringTok = secondParam; // Find second parameter (format string)
     259 [ +  - ][ +  + ]:        900 :             if (formatStringTok && formatStringTok->type() == Token::eString) {
                 [ +  + ]
     260         [ +  - ]:        810 :                 argListTok = formatStringTok->nextArgument(); // Find third parameter (first argument of va_args)
     261 [ +  - ][ +  - ]:        810 :                 formatString = formatStringTok->strValue();
                 [ +  - ]
     262                 :            :             }
     263 [ +  - ][ +  - ]:        180 :         } else if (Token::Match(&tok, "snprintf|fnprintf|swprintf") && secondParam) {
         [ +  - ][ +  - ]
     264         [ +  - ]:        180 :             const Token* formatStringTok = secondParam->nextArgument(); // Find third parameter (format string)
     265 [ +  - ][ +  - ]:        180 :             if (formatStringTok && formatStringTok->type() == Token::eString) {
                 [ +  - ]
     266         [ +  - ]:        180 :                 argListTok = formatStringTok->nextArgument(); // Find fourth parameter (first argument of va_args)
     267 [ +  - ][ +  - ]:        180 :                 formatString = formatStringTok->strValue();
                 [ +  - ]
     268                 :            :             }
     269                 :            :         }
     270                 :            : 
     271         [ +  + ]:       2792 :         if (argListTok) {
     272                 :       2702 :             bool percent = false;
     273 [ +  - ][ +  - ]:      13236 :             for (std::string::iterator i = formatString.begin(); i != formatString.end(); ++i) {
         [ +  - ][ +  - ]
     274         [ +  + ]:      10534 :                 if (*i == '%') {
     275                 :       3782 :                     percent = !percent;
     276         [ +  + ]:       6752 :                 } else if (percent) {
     277                 :       3602 :                     percent = false;
     278                 :            : 
     279                 :       3602 :                     bool _continue = false;
     280         [ +  + ]:       4052 :                     while (!std::isalpha(*i)) {
     281         [ +  + ]:        540 :                         if (*i == '*') {
     282         [ +  + ]:        360 :                             if (scan)
     283                 :         90 :                                 _continue = true;
     284                 :            :                             else
     285         [ +  - ]:        270 :                                 argListTok = argListTok->nextArgument();
     286                 :            :                         }
     287                 :        540 :                         ++i;
     288 [ +  + ][ +  - ]:        540 :                         if (!argListTok || i == formatString.end())
         [ +  - ][ -  + ]
                 [ +  + ]
     289                 :            :                             return;
     290                 :            :                     }
     291         [ +  + ]:       3512 :                     if (_continue)
     292                 :         90 :                         continue;
     293                 :            : 
     294 [ +  - ][ +  + ]:       3422 :                     if ((*i == 'n' || *i == 's' || scan) && (!scan || value == 0)) {
         [ +  + ][ +  + ]
         [ +  - ][ +  + ]
     295 [ +  + ][ +  - ]:       2342 :                         if ((value == 0 && argListTok->str() == "0") || (argListTok->varId() > 0)) {
         [ +  + ][ +  + ]
                 [ +  + ]
     296         [ +  - ]:       1892 :                             var.push_back(argListTok);
     297                 :            :                         }
     298                 :            :                     }
     299                 :            : 
     300         [ +  + ]:       3422 :                     if (*i != 'm') // %m is a non-standard glibc extension that requires no parameter
     301         [ +  - ]:       3332 :                         argListTok = argListTok->nextArgument(); // Find next argument
     302         [ +  + ]:       3422 :                     if (!argListTok)
     303                 :       2612 :                         break;
     304                 :            :                 }
     305                 :            :             }
     306                 :      25321 :         }
     307                 :            :     }
     308                 :            : }
     309                 :            : 
     310                 :            : 
     311                 :            : /**
     312                 :            :  * Is there a pointer dereference? Everything that should result in
     313                 :            :  * a nullpointer dereference error message will result in a true
     314                 :            :  * return value. If it's unknown if the pointer is dereferenced false
     315                 :            :  * is returned.
     316                 :            :  * @param tok token for the pointer
     317                 :            :  * @param unknown it is not known if there is a pointer dereference (could be reported as a debug message)
     318                 :            :  * @return true => there is a dereference
     319                 :            :  */
     320                 :      45337 : bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown)
     321                 :            : {
     322                 :      45337 :     const bool inconclusive = unknown;
     323                 :            : 
     324                 :      45337 :     unknown = false;
     325                 :            : 
     326                 :            :     // Dereferencing pointer..
     327 [ +  + ][ +  + ]:      45337 :     if (tok->strAt(-1) == "*" && (Token::Match(tok->tokAt(-2), "return|throw|;|{|}|:|[|(|,") || tok->tokAt(-2)->isOp()) && !Token::Match(tok->tokAt(-3), "sizeof|decltype"))
         [ +  + ][ +  + ]
                 [ +  + ]
     328                 :       4095 :         return true;
     329                 :            : 
     330                 :            :     // read/write member variable
     331 [ +  + ][ +  - ]:      41242 :     if (!Token::simpleMatch(tok->tokAt(-2), "& (") && !Token::Match(tok->tokAt(-2), "sizeof|decltype (") && tok->strAt(-1) != "&" && Token::Match(tok->next(), ". %var%")) {
         [ +  + ][ +  + ]
                 [ +  + ]
     332         [ +  + ]:       5132 :         if (tok->strAt(3) != "(")
     333                 :       3197 :             return true;
     334                 :       1935 :         unknown = true;
     335                 :       1935 :         return false;
     336                 :            :     }
     337                 :            : 
     338 [ +  + ][ -  + ]:      36110 :     if (Token::Match(tok, "%var% [") && (tok->previous()->str() != "&" || Token::Match(tok->next()->link()->next(), "[.(]")))
         [ #  # ][ +  + ]
     339                 :        721 :         return true;
     340                 :            : 
     341         [ +  + ]:      35389 :     if (Token::Match(tok, "%var% ("))
     342                 :        180 :         return true;
     343                 :            : 
     344   [ +  +  +  -  :      37371 :     if (Token::Match(tok, "%var% = %var% .") &&
           +  + ][ +  + ]
     345                 :       1081 :         tok->varId() > 0 &&
     346                 :       1081 :         tok->varId() == tok->tokAt(2)->varId())
     347                 :        675 :         return true;
     348                 :            : 
     349                 :            :     // std::string dereferences nullpointers
     350         [ +  + ]:      34534 :     if (Token::Match(tok->tokAt(-4), "std :: string|wstring ( %var% )"))
     351                 :         45 :         return true;
     352         [ +  + ]:      34489 :     if (Token::Match(tok->tokAt(-2), "%var% ( %var% )")) {
     353                 :       3607 :         const Variable* var = tok->tokAt(-2)->variable();
     354 [ +  + ][ +  - ]:       3607 :         if (var && !var->isPointer() && !var->isArray() && Token::Match(var->typeStartToken(), "std :: string|wstring !!::"))
         [ +  - ][ +  + ]
                 [ +  + ]
     355                 :         45 :             return true;
     356                 :            :     }
     357                 :            : 
     358                 :            :     // streams dereference nullpointers
     359         [ +  + ]:      34444 :     if (Token::Match(tok->previous(), "<<|>> %var%")) {
     360                 :        720 :         const Variable* var = tok->variable();
     361 [ +  - ][ +  + ]:        720 :         if (var && var->isPointer() && Token::Match(var->typeStartToken(), "char|wchar_t")) { // Only outputting or reading to char* can cause problems
         [ +  + ][ +  + ]
     362                 :        495 :             const Token* tok2 = tok->previous(); // Find start of statement
     363         [ +  - ]:       2070 :             for (; tok2; tok2 = tok2->previous()) {
     364         [ +  + ]:       2070 :                 if (Token::Match(tok2->previous(), ";|{|}|:"))
     365                 :        495 :                     break;
     366                 :            :             }
     367         [ +  + ]:        495 :             if (Token::Match(tok2, "std :: cout|cin|cerr"))
     368                 :        360 :                 return true;
     369 [ +  - ][ +  - ]:        135 :             if (tok2 && tok2->varId() != 0) {
                 [ +  - ]
     370                 :        135 :                 const Variable* var2 = tok2->variable();
     371 [ +  - ][ +  - ]:        135 :                 if (var2 && Token::Match(var2->typeStartToken(), "std :: istream|ifstream|istringstream|wistringstream|ostream|ofstream|ostringstream|wostringstream|stringstream|wstringstream|fstream|iostream"))
                 [ +  - ]
     372                 :        135 :                     return true;
     373                 :            :             }
     374                 :            :         }
     375                 :            :     }
     376                 :            : 
     377                 :      33949 :     const Variable *ovar = NULL;
     378         [ +  + ]:      33949 :     if (Token::Match(tok, "%var% ==|!= %var%"))
     379                 :        225 :         ovar = tok->tokAt(2)->variable();
     380         [ +  + ]:      33724 :     else if (Token::Match(tok->tokAt(-2), "%var% ==|!= %var%"))
     381                 :        225 :         ovar = tok->tokAt(-2)->variable();
     382         [ +  + ]:      33499 :     else if (Token::Match(tok->tokAt(-2), "%var% =|+ %var% )|]|,|;|+"))
     383                 :        270 :         ovar = tok->tokAt(-2)->variable();
     384 [ +  + ][ +  + ]:      33949 :     if (ovar && !ovar->isPointer() && !ovar->isArray() && Token::Match(ovar->typeStartToken(), "std :: string|wstring !!::"))
         [ +  - ][ +  - ]
                 [ +  + ]
     385                 :        225 :         return true;
     386                 :            : 
     387                 :            :     // Check if it's NOT a pointer dereference.
     388                 :            :     // This is most useful in inconclusive checking
     389         [ +  + ]:      33724 :     if (inconclusive) {
     390                 :            :         // Not a dereference..
     391         [ +  + ]:       7290 :         if (Token::Match(tok, "%var% ="))
     392                 :       2295 :             return false;
     393                 :            : 
     394                 :            :         // OK to delete a null
     395 [ +  + ][ +  + ]:       4995 :         if (Token::Match(tok->previous(), "delete %var%") || Token::Match(tok->tokAt(-3), "delete [ ] %var%"))
                 [ +  + ]
     396                 :         90 :             return false;
     397                 :            : 
     398                 :            :         // OK to check if pointer is null
     399                 :            :         // OK to take address of pointer
     400         [ +  + ]:       4905 :         if (Token::Match(tok->previous(), "!|& %var%"))
     401                 :        855 :             return false;
     402                 :            : 
     403                 :            :         // OK to check pointer in "= p ? : "
     404   [ +  +  +  -  :       4140 :         if (tok->next()->str() == "?" &&
           +  - ][ +  + ]
     405                 :         90 :             (Token::Match(tok->previous(), "return|throw|;|{|}|:|[|(|,") || tok->previous()->isAssignmentOp()))
     406                 :         45 :             return false;
     407                 :            : 
     408                 :            :         // OK to pass pointer to function
     409   [ +  +  +  -  :       6255 :         if (Token::Match(tok->previous(), "[(,] %var% [,)]") &&
           +  + ][ +  + ]
     410                 :       1125 :             (!Token::Match(tok->previous(), "( %var%") ||
     411                 :       1125 :              Token::Match(tok->tokAt(-2), "%var% ( %var%")))
     412                 :       1080 :             return false;
     413                 :            : 
     414                 :            :         // Compare pointer
     415         [ +  + ]:       2925 :         if (Token::Match(tok->previous(), "(|&&|%oror%|==|!= %var%"))
     416                 :        540 :             return false;
     417         [ +  + ]:       2385 :         if (Token::Match(tok, "%var% &&|%oror%|==|!=|)"))
     418                 :         45 :             return false;
     419                 :            : 
     420                 :            :         // Taking address
     421         [ +  + ]:       2340 :         if (Token::Match(tok->previous(), "return|= %var% ;"))
     422                 :         90 :             return false;
     423                 :            : 
     424                 :            :         // (void)var
     425         [ +  + ]:       2250 :         if (Token::Match(tok->previous(), "[{;}] %var% ;"))
     426                 :         45 :             return false;
     427                 :            : 
     428                 :            :         // Shift pointer (e.g. to cout, but its no char* (see above))
     429         [ +  + ]:       2205 :         if (Token::Match(tok->previous(), "<<|>> %var%"))
     430                 :        135 :             return false;
     431                 :            : 
     432                 :            :         // unknown if it's a dereference
     433                 :       2070 :         unknown = true;
     434                 :            :     }
     435                 :            : 
     436                 :            :     // assume that it's not a dereference (no false positives)
     437                 :      45337 :     return false;
     438                 :            : }
     439                 :            : 
     440                 :            : 
     441                 :            : // check if function can assign pointer
     442                 :       1890 : bool CheckNullPointer::CanFunctionAssignPointer(const Token *functiontoken, unsigned int varid, bool& unknown)
     443                 :            : {
     444         [ +  + ]:       1890 :     if (Token::Match(functiontoken, "if|while|for|switch|sizeof|catch"))
     445                 :        765 :         return false;
     446                 :            : 
     447                 :       1125 :     unsigned int argumentNumber = 0;
     448         [ +  + ]:       1665 :     for (const Token *arg = functiontoken->tokAt(2); arg; arg = arg->nextArgument()) {
     449         [ +  + ]:       1125 :         if (Token::Match(arg, "%varid% [,)]", varid)) {
     450                 :        585 :             const Function* func = functiontoken->function();
     451         [ +  + ]:        585 :             if (!func) { // Unknown function
     452                 :        270 :                 unknown = true;
     453                 :        270 :                 return true; // assume that the function might assign the pointer
     454                 :            :             }
     455                 :            : 
     456                 :        315 :             const Variable* var = func->getArgumentVar(argumentNumber);
     457         [ -  + ]:        315 :             if (!var) { // Unknown variable
     458                 :          0 :                 unknown = true;
     459                 :          0 :                 return true;
     460         [ +  + ]:        315 :             } else if (var->isReference()) // Assume every pointer passed by reference is assigned
     461                 :         45 :                 return true;
     462                 :            :             else
     463                 :        270 :                 return false;
     464                 :            :         }
     465                 :        540 :         ++argumentNumber;
     466                 :            :     }
     467                 :            : 
     468                 :            :     // pointer is not passed
     469                 :       1890 :     return false;
     470                 :            : }
     471                 :            : 
     472                 :            : 
     473                 :            : 
     474                 :      12391 : void CheckNullPointer::nullPointerLinkedList()
     475                 :            : {
     476                 :      12391 :     const SymbolDatabase* const symbolDatabase = _tokenizer->getSymbolDatabase();
     477                 :            : 
     478                 :            :     // looping through items in a linked list in a inner loop.
     479                 :            :     // Here is an example:
     480                 :            :     //    for (const Token *tok = tokens; tok; tok = tok->next) {
     481                 :            :     //        if (tok->str() == "hello")
     482                 :            :     //            tok = tok->next;   // <- tok might become a null pointer!
     483                 :            :     //    }
     484         [ +  + ]:      49674 :     for (std::list<Scope>::const_iterator i = symbolDatabase->scopeList.begin(); i != symbolDatabase->scopeList.end(); ++i) {
     485                 :      37283 :         const Token* const tok1 = i->classDef;
     486                 :            :         // search for a "for" scope..
     487 [ +  + ][ -  + ]:      37283 :         if (i->type != Scope::eFor || !tok1)
                 [ +  + ]
     488                 :      36743 :             continue;
     489                 :            : 
     490                 :            :         // is there any dereferencing occurring in the for statement
     491                 :        540 :         const Token* end2 = tok1->linkAt(1);
     492         [ +  + ]:       7920 :         for (const Token *tok2 = tok1->tokAt(2); tok2 != end2; tok2 = tok2->next()) {
     493                 :            :             // Dereferencing a variable inside the "for" parentheses..
     494         [ +  + ]:       7380 :             if (Token::Match(tok2, "%var% . %var%")) {
     495                 :            :                 // Is this variable a pointer?
     496                 :        270 :                 const Variable *var = tok2->variable();
     497 [ +  + ][ +  + ]:        270 :                 if (!var || !var->isPointer())
                 [ +  + ]
     498                 :         90 :                     continue;
     499                 :            : 
     500                 :            :                 // Variable id for dereferenced variable
     501                 :        180 :                 const unsigned int varid(tok2->varId());
     502                 :            : 
     503         [ +  + ]:        180 :                 if (Token::Match(tok2->tokAt(-2), "%varid% ?", varid))
     504                 :         45 :                     continue;
     505                 :            : 
     506                 :            :                 // Check usage of dereferenced variable in the loop..
     507         [ +  + ]:        360 :                 for (std::list<Scope*>::const_iterator j = i->nestedList.begin(); j != i->nestedList.end(); ++j) {
     508                 :        225 :                     Scope* scope = *j;
     509         [ +  + ]:        225 :                     if (scope->type != Scope::eWhile)
     510                 :         90 :                         continue;
     511                 :            : 
     512                 :            :                     // TODO: are there false negatives for "while ( %varid% ||"
     513         [ +  - ]:        135 :                     if (Token::Match(scope->classDef->next(), "( %varid% &&|)", varid)) {
     514                 :            :                         // Make sure there is a "break" or "return" inside the loop.
     515                 :            :                         // Without the "break" a null pointer could be dereferenced in the
     516                 :            :                         // for statement.
     517         [ +  - ]:       2160 :                         for (const Token *tok4 = scope->classStart; tok4; tok4 = tok4->next()) {
     518         [ +  + ]:       2025 :                             if (tok4 == i->classEnd) {
     519                 :         45 :                                 nullPointerError(tok1, var->name(), scope->classDef);
     520                 :         45 :                                 break;
     521                 :            :                             }
     522                 :            : 
     523                 :            :                             // There is a "break" or "return" inside the loop.
     524                 :            :                             // TODO: there can be false negatives. There could still be
     525                 :            :                             //       execution paths that are not properly terminated
     526 [ +  + ][ +  + ]:       1980 :                             else if (tok4->str() == "break" || tok4->str() == "return")
                 [ +  + ]
     527                 :         90 :                                 break;
     528                 :            :                         }
     529                 :            :                     }
     530                 :            :                 }
     531                 :            :             }
     532                 :            :         }
     533                 :            :     }
     534                 :      12391 : }
     535                 :            : 
     536                 :      11655 : void CheckNullPointer::nullPointerStructByDeRefAndChec()
     537                 :            : {
     538                 :            :     // Dereferencing a struct pointer and then checking if it's NULL..
     539                 :      11655 :     const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
     540                 :            : 
     541                 :            :     // skipvar: don't check vars that has been tested against null already
     542                 :      11655 :     std::set<unsigned int> skipvar;
     543         [ +  - ]:      11655 :     skipvar.insert(0);
     544                 :            : 
     545                 :      11655 :     const std::size_t functions = symbolDatabase->functionScopes.size();
     546         [ +  + ]:      23580 :     for (std::size_t i = 0; i < functions; ++i) {
     547                 :      11925 :         const Scope * scope = symbolDatabase->functionScopes[i];
     548 [ +  - ][ -  + ]:      11925 :         if (scope->function == 0 || !scope->function->hasBody) // We only look for functions with a body
     549                 :          0 :             continue;
     550         [ +  + ]:     239985 :         for (const Token *tok1 = scope->classStart; tok1 != scope->classEnd; tok1 = tok1->next()) {
     551                 :            :             // Checking if some pointer is null.
     552                 :            :             // then add the pointer to skipvar => is it known that it isn't NULL
     553 [ +  - ][ +  + ]:     228060 :             if (Token::Match(tok1, "if|while ( !| %var% )")) {
     554         [ +  - ]:       6615 :                 tok1 = tok1->tokAt(2);
     555 [ +  - ][ +  + ]:       6615 :                 if (tok1->str() == "!")
     556                 :       3465 :                     tok1 = tok1->next();
     557         [ +  - ]:       6615 :                 skipvar.insert(tok1->varId());
     558                 :       6615 :                 continue;
     559 [ +  - ][ +  + ]:     442530 :             } else if (Token::Match(tok1, "( ! %var% %oror%") ||
         [ +  + ][ +  + ]
     560         [ +  - ]:     221085 :                        Token::Match(tok1, "( %var% &&")) {
     561                 :            :                 // TODO: there are false negatives caused by this. The
     562                 :            :                 // variable should be removed from skipvar after the
     563                 :            :                 // condition
     564                 :       1215 :                 tok1 = tok1->next();
     565 [ +  - ][ +  + ]:       1215 :                 if (tok1->str() == "!")
     566                 :        360 :                     tok1 = tok1->next();
     567         [ +  - ]:       1215 :                 skipvar.insert(tok1->varId());
     568                 :       1215 :                 continue;
     569                 :            :             }
     570                 :            : 
     571                 :     220230 :             bool inconclusive = false;
     572                 :            : 
     573                 :            :             /**
     574                 :            :              * @todo There are lots of false negatives here. A dereference
     575                 :            :              *  is only investigated if a few specific conditions are met.
     576                 :            :              */
     577                 :            : 
     578                 :            :             // dereference in assignment
     579 [ +  - ][ +  + ]:     220230 :             if (Token::Match(tok1, "[;{}] %var% . %var%")) {
     580                 :       1800 :                 tok1 = tok1->next();
     581 [ +  - ][ +  - ]:       1800 :                 if (tok1->strAt(3) == "(") {
                 [ +  + ]
     582         [ +  + ]:       1125 :                     if (!_settings->inconclusive)
     583                 :        720 :                         continue;
     584                 :        405 :                     inconclusive = true;
     585                 :            :                 }
     586                 :            :             }
     587                 :            : 
     588                 :            :             // dereference in assignment
     589 [ +  - ][ +  + ]:     218430 :             else if (Token::Match(tok1, "[{};] %var% = %var% . %var%")) {
     590 [ +  - ][ +  - ]:       1485 :                 if (tok1->strAt(1) == tok1->strAt(3))
         [ +  - ][ +  + ]
     591                 :        990 :                     continue;
     592         [ +  - ]:        495 :                 tok1 = tok1->tokAt(3);
     593                 :            :             }
     594                 :            : 
     595                 :            :             // dereference in condition
     596 [ +  - ][ +  + ]:     216945 :             else if (Token::Match(tok1, "if ( !| %var% .")) {
     597         [ +  - ]:        405 :                 tok1 = tok1->tokAt(2);
     598 [ +  - ][ +  + ]:        405 :                 if (tok1->str() == "!")
     599                 :         90 :                     tok1 = tok1->next();
     600                 :            :             }
     601                 :            : 
     602                 :            :             // dereference in function call (but not sizeof|decltype)
     603 [ +  - ][ +  - ]:     432765 :             else if ((Token::Match(tok1->tokAt(-2), "%var% ( %var% . %var%") && !Token::Match(tok1->tokAt(-2), "sizeof|decltype ( %var% . %var%")) ||
         [ +  + ][ +  - ]
         [ +  - ][ +  + ]
         [ +  + ][ +  + ]
     604         [ +  - ]:     216225 :                      Token::Match(tok1->previous(), ", %var% . %var%")) {
     605                 :            :                 // Is the function return value taken by the pointer?
     606                 :        360 :                 bool assignment = false;
     607                 :        360 :                 const unsigned int varid1(tok1->varId());
     608         [ -  + ]:        360 :                 if (varid1 == 0)
     609                 :          0 :                     continue;
     610                 :        360 :                 const Token *tok2 = tok1->previous();
     611 [ +  - ][ +  - ]:       2025 :                 while (tok2 && !Token::Match(tok2, "[;{}]")) {
         [ +  + ][ +  + ]
     612 [ +  - ][ +  + ]:       1755 :                     if (Token::Match(tok2, "%varid% =", varid1)) {
     613                 :         90 :                         assignment = true;
     614                 :         90 :                         break;
     615                 :            :                     }
     616                 :       1665 :                     tok2 = tok2->previous();
     617                 :            :                 }
     618         [ +  + ]:        360 :                 if (assignment)
     619                 :         90 :                     continue;
     620                 :            : 
     621                 :            :                 // Is the dereference checked with a previous &&
     622                 :        270 :                 bool checked = false;
     623 [ +  - ][ +  - ]:        900 :                 for (tok2 = tok1->tokAt(-2); tok2; tok2 = tok2->previous()) {
     624 [ +  - ][ +  + ]:        900 :                     if (Token::Match(tok2, "[,(;{}]"))
     625                 :        225 :                         break;
     626 [ +  - ][ -  + ]:        675 :                     else if (tok2->str() == ")")
     627                 :          0 :                         tok2 = tok2->link();
     628 [ +  - ][ +  + ]:        675 :                     else if (Token::Match(tok2, "%varid% &&", varid1)) {
     629                 :         45 :                         checked = true;
     630                 :         45 :                         break;
     631                 :            :                     }
     632                 :            :                 }
     633         [ +  + ]:        270 :                 if (checked)
     634                 :         45 :                     continue;
     635                 :            :             }
     636                 :            : 
     637                 :            :             // Goto next token
     638                 :            :             else {
     639                 :     216180 :                 continue;
     640                 :            :             }
     641                 :            : 
     642                 :            :             // struct dereference was found - investigate if it is later
     643                 :            :             // checked that it is not NULL
     644                 :       2205 :             const unsigned int varid1(tok1->varId());
     645 [ +  - ][ +  - ]:       2205 :             if (skipvar.find(varid1) != skipvar.end())
                 [ +  + ]
     646                 :        765 :                 continue;
     647                 :            : 
     648                 :            :             // name of struct pointer
     649                 :       1440 :             const std::string& varname(tok1->str());
     650                 :            : 
     651                 :            :             // is pointer local?
     652                 :       1440 :             bool isLocal = false;
     653                 :       1440 :             const Variable *var = tok1->variable();
     654         [ -  + ]:       1440 :             if (!var)
     655                 :          0 :                 continue;
     656 [ +  - ][ +  + ]:       1440 :             if (var->isLocal() || var->isArgument())
         [ +  + ][ +  + ]
     657                 :       1395 :                 isLocal = true;
     658                 :            : 
     659                 :            :             // member function may or may not nullify the pointer if it's global (#2647)
     660         [ +  + ]:       1440 :             if (!isLocal) {
     661                 :         45 :                 const Token *tok2 = tok1;
     662 [ +  - ][ +  + ]:         90 :                 while (Token::Match(tok2, "%var% ."))
     663         [ +  - ]:         45 :                     tok2 = tok2->tokAt(2);
     664 [ +  - ][ -  + ]:         45 :                 if (Token::Match(tok2,"%var% ("))
     665                 :          0 :                     continue;
     666                 :            :             }
     667                 :            : 
     668                 :            :             // count { and } using tok2
     669                 :       1440 :             const Token* const end2 = tok1->scope()->classEnd;
     670 [ +  - ][ +  + ]:       9765 :             for (const Token *tok2 = tok1->tokAt(3); tok2 != end2; tok2 = tok2->next()) {
     671                 :       9315 :                 bool unknown = false;
     672                 :            : 
     673                 :            :                 // label / ?:
     674 [ +  - ][ +  + ]:       9315 :                 if (tok2->str() == ":")
     675                 :         90 :                     break;
     676                 :            : 
     677                 :            :                 // function call..
     678 [ +  - ][ +  + ]:       9225 :                 else if (Token::Match(tok2, "[;{}] %var% (") && CanFunctionAssignPointer(tok2->next(), varid1, unknown)) {
         [ +  - ][ +  + ]
                 [ +  + ]
     679 [ +  + ][ -  + ]:         90 :                     if (!_settings->inconclusive || !unknown)
     680                 :         45 :                         break;
     681                 :         45 :                     inconclusive = true;
     682                 :            :                 }
     683                 :            : 
     684                 :            :                 // Reassignment of the struct
     685         [ +  + ]:       9135 :                 else if (tok2->varId() == varid1) {
     686 [ +  - ][ +  + ]:        450 :                     if (tok2->next()->str() == "=") {
     687                 :            :                         // Avoid false positives when there is 'else if'
     688                 :            :                         // TODO: can this be handled better?
     689 [ +  - ][ +  - ]:         90 :                         if (tok1->strAt(-2) == "if")
                 [ +  + ]
     690         [ +  - ]:         45 :                             skipvar.insert(varid1);
     691                 :         90 :                         break;
     692                 :            :                     }
     693 [ +  - ][ +  - ]:        360 :                     if (Token::Match(tok2->tokAt(-2), "[,(] &"))
                 [ +  + ]
     694                 :         45 :                         break;
     695                 :            :                 }
     696                 :            : 
     697                 :            :                 // Loop..
     698                 :            :                 /** @todo don't bail out if the variable is not used in the loop */
     699 [ +  - ][ +  + ]:       8685 :                 else if (tok2->str() == "do")
     700                 :         45 :                     break;
     701                 :            : 
     702                 :            :                 // return/break at base level => stop checking
     703 [ +  + ][ +  - ]:       8640 :                 else if (tok2->scope()->classEnd == end2 && (tok2->str() == "return" || tok2->str() == "break"))
         [ +  - ][ +  - ]
         [ +  + ][ +  + ]
     704                 :         45 :                     break;
     705                 :            : 
     706                 :            :                 // Function call: If the pointer is not a local variable it
     707                 :            :                 // might be changed by the call.
     708 [ +  - ][ +  + ]:       9630 :                 else if (Token::Match(tok2, "[;{}] %var% (") &&
         [ +  + ][ +  + ]
                 [ +  + ]
     709 [ +  - ][ +  - ]:       1035 :                          Token::simpleMatch(tok2->linkAt(2), ") ;") && !isLocal) {
     710                 :         45 :                     break;
     711                 :            :                 }
     712                 :            : 
     713                 :            :                 // Check if pointer is null.
     714                 :            :                 // TODO: false negatives for "if (!p || .."
     715 [ +  + ][ +  - ]:       8550 :                 else if (!tok2->isExpandedMacro() && Token::Match(tok2, "if ( !| %varid% )|&&", varid1)) {
         [ +  + ][ +  + ]
     716                 :            :                     // Is this variable a pointer?
     717         [ +  + ]:        585 :                     if (var->isPointer())
     718         [ +  - ]:        540 :                         nullPointerError(tok1, varname, tok2, inconclusive);
     719                 :        585 :                     break;
     720                 :            :                 }
     721                 :            :             }
     722                 :            :         }
     723                 :      11655 :     }
     724                 :      11655 : }
     725                 :            : 
     726                 :      11655 : void CheckNullPointer::nullPointerByDeRefAndChec()
     727                 :            : {
     728                 :      11655 :     const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
     729                 :            : 
     730                 :            :     // Dereferencing a pointer and then checking if it's NULL..
     731                 :            :     // This check will first scan for the check. And then scan backwards
     732                 :            :     // from the check, searching for dereferencing.
     733         [ +  + ]:      45945 :     for (std::list<Scope>::const_iterator i = symbolDatabase->scopeList.begin(); i != symbolDatabase->scopeList.end(); ++i) {
     734                 :            :         // TODO: false negatives.
     735                 :            :         // - logical operators
     736                 :      34290 :         const Token* tok = i->classDef;
     737 [ +  + ][ +  + ]:      50760 :         if ((i->type == Scope::eIf || i->type == Scope::eElseIf || i->type == Scope::eWhile) &&
         [ +  + ][ +  -  
             +  +  +  + ]
                 [ +  + ]
     738                 :      16470 :             tok && Token::Match(tok, "else| %var% ( !| %var% )|%oror%|&&") && !tok->next()->isExpandedMacro()) {
     739                 :            : 
     740         [ -  + ]:       7515 :             if (tok->str() == "else")
     741                 :          0 :                 tok = tok->next();
     742                 :            : 
     743                 :       7515 :             const Token * vartok = tok->tokAt(2);
     744         [ +  + ]:       7515 :             if (vartok->str() == "!")
     745                 :       3645 :                 vartok = vartok->next();
     746                 :            : 
     747                 :       7515 :             const Variable *var = vartok->variable();
     748                 :            :             // Check that variable is a pointer..
     749 [ +  + ][ +  + ]:       7515 :             if (!var || !var->isPointer())
                 [ +  + ]
     750                 :        990 :                 continue;
     751                 :            : 
     752                 :            :             // Variable id for pointer
     753                 :       6525 :             const unsigned int varid(vartok->varId());
     754                 :            : 
     755                 :            :             // Name of pointer
     756                 :       6525 :             const std::string& varname(vartok->str());
     757                 :            : 
     758                 :       6525 :             const Token * const decltok = var->nameToken();
     759                 :       6525 :             bool inconclusive = false;
     760                 :            : 
     761 [ +  - ][ +  + ]:      30330 :             for (const Token *tok1 = tok->previous(); tok1 && tok1 != decltok; tok1 = tok1->previous()) {
                 [ +  + ]
     762 [ +  + ][ +  + ]:      23805 :                 if (tok1->str() == ")" && Token::Match(tok1->link()->previous(), "%var% (")) {
                 [ +  + ]
     763                 :       1845 :                     const Token *tok2 = tok1->link();
     764 [ +  - ][ +  + ]:       7290 :                     while (tok2 && !Token::Match(tok2, "[;{}?:]"))
                 [ +  + ]
     765                 :       5445 :                         tok2 = tok2->previous();
     766         [ +  + ]:       1845 :                     if (Token::Match(tok2, "[?:]"))
     767                 :         45 :                         break;
     768         [ +  + ]:       1800 :                     if (Token::Match(tok2->next(), "%varid% = %var%", varid))
     769                 :        270 :                         break;
     770                 :            : 
     771         [ +  + ]:       1530 :                     if (Token::Match(tok2->next(), "while ( %varid%", varid))
     772                 :         45 :                         break;
     773                 :            : 
     774   [ +  +  +  + ]:       2790 :                     if (Token::Match(tok1->link(), "( ! %varid% %oror%", varid) ||
                 [ +  + ]
     775                 :       1305 :                         Token::Match(tok1->link(), "( %varid% &&", varid)) {
     776                 :        270 :                         tok1 = tok1->link();
     777                 :        270 :                         continue;
     778                 :            :                     }
     779                 :            : 
     780         [ +  + ]:       1215 :                     if (Token::simpleMatch(tok1->link()->previous(), "sizeof (")) {
     781                 :        180 :                         tok1 = tok1->link()->previous();
     782                 :        180 :                         continue;
     783                 :            :                     }
     784                 :            : 
     785         [ +  + ]:       1035 :                     if (Token::Match(tok2->next(), "%var% ( %varid% ,", varid)) {
     786                 :         45 :                         std::list<const Token *> varlist;
     787         [ +  - ]:         45 :                         parseFunctionCall(*(tok2->next()), varlist, 0);
     788 [ +  - ][ +  - ]:         45 :                         if (!varlist.empty() && varlist.front() == tok2->tokAt(3)) {
         [ +  - ][ +  - ]
                 [ +  - ]
     789 [ +  - ][ +  - ]:         45 :                             nullPointerError(tok2->tokAt(3), varname, tok, inconclusive);
     790                 :            :                             break;
     791         [ -  + ]:         45 :                         }
     792                 :            :                     }
     793                 :            : 
     794                 :            :                     // Passing pointer as parameter..
     795         [ +  + ]:        990 :                     if (Token::Match(tok2->next(), "%type% (")) {
     796                 :        765 :                         bool unknown = false;
     797         [ +  + ]:        765 :                         if (CanFunctionAssignPointer(tok2->next(), varid, unknown)) {
     798 [ +  + ][ +  + ]:        225 :                             if (!_settings->inconclusive || !unknown)
     799                 :        135 :                                 break;
     800                 :         90 :                             inconclusive = true;
     801                 :            :                         }
     802                 :            :                     }
     803                 :            : 
     804                 :            :                     // calling unknown function => it might initialize the pointer
     805 [ +  + ][ +  + ]:        855 :                     if (!(var->isLocal() || var->isArgument()))
                 [ +  + ]
     806                 :        135 :                         break;
     807                 :            :                 }
     808                 :            : 
     809         [ +  + ]:      22680 :                 if (tok1->str() == "break")
     810                 :         45 :                     break;
     811                 :            : 
     812         [ +  + ]:      22635 :                 if (tok1->varId() == varid) {
     813                 :            :                     // Don't write warning if the dereferencing is
     814                 :            :                     // guarded by ?: or &&
     815                 :       2565 :                     const Token *tok2 = tok1->previous();
     816 [ +  - ][ +  + ]:       2565 :                     if (tok2 && (tok2->isArithmeticalOp() || tok2->str() == "(")) {
         [ +  + ][ +  + ]
     817 [ +  - ][ +  + ]:       3240 :                         while (tok2 && !Token::Match(tok2, "[;{}?:]")) {
                 [ +  + ]
     818         [ +  + ]:       2160 :                             if (tok2->str() == ")") {
     819                 :         45 :                                 tok2 = tok2->link();
     820         [ +  - ]:         45 :                                 if (Token::Match(tok2, "( %varid% =", varid)) {
     821                 :         45 :                                     tok2 = tok2->next();
     822                 :         45 :                                     break;
     823                 :            :                                 }
     824                 :            :                             }
     825                 :            :                             // guarded by &&
     826 [ +  + ][ +  + ]:       2115 :                             if (tok2->varId() == varid && tok2->next()->str() == "&&")
                 [ +  + ]
     827                 :         45 :                                 break;
     828                 :       2070 :                             tok2 = tok2->previous();
     829                 :            :                         }
     830                 :            :                     }
     831 [ +  - ][ +  + ]:       2565 :                     if (!tok2 || Token::Match(tok2, "[?:]") || tok2->varId() == varid)
         [ +  + ][ +  + ]
     832                 :        315 :                         continue;
     833                 :            : 
     834                 :            :                     // unknown : this is set by isPointerDeRef if it is
     835                 :            :                     //           uncertain
     836                 :       2250 :                     bool unknown = _settings->inconclusive;
     837                 :            : 
     838                 :            :                     // reassign : is the pointer reassigned like this:
     839                 :            :                     //            tok = tok->next();
     840                 :       2250 :                     bool reassign = false;
     841         [ +  + ]:       2250 :                     if (Token::Match(tok1->previous(), "= %varid% .", varid)) {
     842                 :        225 :                         const Token *back = tok1->tokAt(-2);
     843         [ +  - ]:        630 :                         while (back) {
     844         [ +  + ]:        405 :                             if (back->varId() == varid) {
     845                 :        180 :                                 reassign = true;
     846                 :        180 :                                 break;
     847                 :            :                             }
     848         [ +  + ]:        225 :                             if (Token::Match(back, "[{};,(]")) {
     849                 :         45 :                                 break;
     850                 :            :                             }
     851                 :        180 :                             back = back->previous();
     852                 :            :                         }
     853         [ +  + ]:       2025 :                     } else if (Token::Match(tok1->tokAt(-4), "%varid% = ( * %varid%", varid)) {
     854                 :         45 :                         reassign = true;
     855         [ +  + ]:       1980 :                     } else if (Token::Match(tok1->tokAt(-3), "%varid% = * %varid%", varid)) {
     856                 :         45 :                         reassign = true;
     857                 :            :                     }
     858                 :            : 
     859         [ +  + ]:       2250 :                     if (reassign) {
     860                 :        270 :                         break;
     861   [ +  +  +  - ]:       2025 :                     } else if (Token::simpleMatch(tok1->tokAt(-2), "* )") &&
                 [ +  + ]
     862                 :         45 :                                Token::Match(tok1->linkAt(-1)->tokAt(-2), "%varid% = (", tok1->varId())) {
     863                 :         45 :                         break;
     864   [ -  +  #  # ]:       1935 :                     } else if (Token::simpleMatch(tok1->tokAt(-3), "* ) (") &&
                 [ -  + ]
     865                 :          0 :                                Token::Match(tok1->linkAt(-2)->tokAt(-2), "%varid% = (", tok1->varId())) {
     866                 :          0 :                         break;
     867         [ +  + ]:       1935 :                     } else if (Token::Match(tok1->previous(), "&&|%oror%")) {
     868                 :         45 :                         break;
     869         [ -  + ]:       1890 :                     } else if (Token::Match(tok1->tokAt(-2), "&&|%oror% !")) {
     870                 :          0 :                         break;
     871         [ +  + ]:       1890 :                     } else if (CheckNullPointer::isPointerDeRef(tok1, unknown)) {
     872                 :        720 :                         nullPointerError(tok1, varname, tok, inconclusive);
     873                 :        720 :                         break;
     874         [ +  + ]:       1170 :                     } else if (tok1->strAt(-1) == "&") {
     875                 :         90 :                         break;
     876         [ +  + ]:       1080 :                     } else if (tok1->strAt(1) == "=") {
     877                 :        495 :                         break;
     878                 :            :                     }
     879                 :            :                 }
     880                 :            : 
     881   [ +  +  +  + ]:      36855 :                 else if (tok1->str() == "{" ||
                 [ +  + ]
     882                 :      16785 :                          tok1->str() == "}")
     883                 :       3870 :                     break;
     884                 :            : 
     885                 :            :                 // label..
     886         [ +  + ]:      16200 :                 else if (Token::Match(tok1, "%type% :"))
     887                 :         45 :                     break;
     888                 :            :             }
     889                 :            :         }
     890                 :            :     }
     891                 :      11655 : }
     892                 :            : 
     893                 :      11655 : void CheckNullPointer::nullPointerByCheckAndDeRef()
     894                 :            : {
     895                 :      11655 :     const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
     896                 :            : 
     897                 :            :     // Check if pointer is NULL and then dereference it..
     898         [ +  + ]:      45945 :     for (std::list<Scope>::const_iterator i = symbolDatabase->scopeList.begin(); i != symbolDatabase->scopeList.end(); ++i) {
     899 [ +  + ][ +  + ]:      34290 :         if (i->type != Scope::eIf && i->type != Scope::eElseIf && i->type != Scope::eWhile)
         [ +  + ][ +  + ]
     900                 :      25470 :             continue;
     901 [ +  - ][ +  + ]:       8820 :         if (!i->classDef || i->classDef->isExpandedMacro())
                 [ +  + ]
     902                 :        135 :             continue;
     903                 :            : 
     904         [ +  + ]:       8685 :         const Token* const tok = i->type != Scope::eElseIf ? i->classDef->next() : i->classDef->tokAt(2);
     905                 :            :         // TODO: investigate false negatives:
     906                 :            :         // - handle "while"?
     907                 :            :         // - if there are logical operators
     908                 :            :         // - if (x) { } else { ... }
     909                 :            : 
     910                 :            :         // If the if-body ends with a unknown macro then bailout
     911 [ +  + ][ +  + ]:       8685 :         if (Token::Match(i->classEnd->tokAt(-3), "[;{}] %var% ;") && i->classEnd->tokAt(-2)->isUpperCaseName())
                 [ +  + ]
     912                 :         45 :             continue;
     913                 :            : 
     914                 :            :         // vartok : token for the variable
     915                 :       8640 :         const Token *vartok = 0;
     916                 :       8640 :         const Token *checkConditionStart = 0;
     917         [ +  + ]:       8640 :         if (Token::Match(tok, "( ! %var% )|&&")) {
     918                 :       3510 :             vartok = tok->tokAt(2);
     919                 :       3510 :             checkConditionStart = vartok->next();
     920         [ +  + ]:       5130 :         } else if (Token::Match(tok, "( %var% )|&&")) {
     921                 :       3780 :             vartok = tok->next();
     922         [ +  + ]:       1350 :         } else if (Token::Match(tok, "( ! ( %var% =")) {
     923                 :         90 :             vartok = tok->tokAt(3);
     924         [ +  + ]:         90 :             if (Token::simpleMatch(tok->linkAt(2), ") &&"))
     925                 :         45 :                 checkConditionStart = tok->linkAt(2);
     926                 :            :         } else
     927                 :       1260 :             continue;
     928                 :            : 
     929                 :            :         // Check if variable is a pointer
     930                 :       7380 :         const Variable *var = vartok->variable();
     931 [ +  + ][ +  + ]:       7380 :         if (!var || !var->isPointer())
                 [ +  + ]
     932                 :        990 :             continue;
     933                 :            : 
     934                 :            :         // variable id for pointer
     935                 :       6390 :         const unsigned int varid(vartok->varId());
     936                 :            : 
     937                 :       6390 :         const Scope* declScope = &*i;
     938 [ +  - ][ +  + ]:      13140 :         while (declScope->nestedIn && var->scope() != declScope && declScope->type != Scope::eFunction)
         [ +  + ][ +  + ]
     939                 :       6750 :             declScope = declScope->nestedIn;
     940                 :            : 
     941         [ +  + ]:       6390 :         if (Token::Match(vartok->next(), "&& ( %varid% =", varid))
     942                 :         90 :             continue;
     943                 :            : 
     944                 :            :         // Name and line of the pointer
     945                 :       6300 :         const std::string &pointerName = vartok->str();
     946                 :            : 
     947                 :            :         // Check the condition (eg. ( !x && x->i )
     948         [ +  + ]:       6300 :         if (checkConditionStart) {
     949                 :       3285 :             const Token * const conditionEnd = tok->link();
     950         [ +  + ]:       4005 :             for (const Token *tok2 = checkConditionStart; tok2 != conditionEnd; tok2 = tok2->next()) {
     951                 :            :                 // If we hit a || operator, abort
     952         [ +  + ]:        720 :                 if (tok2->str() == "||")
     953                 :         45 :                     break;
     954                 :            : 
     955                 :            :                 // Pointer is used
     956                 :        675 :                 bool unknown = _settings->inconclusive;
     957 [ +  + ][ -  + ]:        675 :                 if (tok2->varId() == varid && (isPointerDeRef(tok2, unknown) || unknown)) {
         [ #  # ][ +  + ]
     958                 :        135 :                     nullPointerError(tok2, pointerName, vartok, unknown);
     959                 :        135 :                     break;
     960                 :            :                 }
     961                 :            :             }
     962                 :            :         }
     963                 :            : 
     964                 :            :         // start token = inside the if-body
     965                 :       6300 :         const Token *tok1 = i->classStart;
     966                 :            : 
     967         [ +  + ]:       6300 :         if (Token::Match(tok, "( %var% )|&&")) {
     968                 :            :             // start token = first token after the if/while body
     969                 :       2970 :             tok1 = i->classEnd->next();
     970         [ -  + ]:       2970 :             if (!tok1)
     971                 :          0 :                 continue;
     972                 :            :         }
     973                 :            : 
     974                 :       6300 :         int indentlevel = 0;
     975                 :            : 
     976                 :            :         // Set to true if we would normally bail out the check.
     977                 :       6300 :         bool inconclusive = false;
     978                 :            : 
     979                 :            :         // Count { and } for tok2
     980         [ +  + ]:      24840 :         for (const Token *tok2 = tok1; tok2 != declScope->classEnd; tok2 = tok2->next()) {
     981         [ +  + ]:      20925 :             if (tok2->str() == "{")
     982                 :       3690 :                 ++indentlevel;
     983         [ +  + ]:      17235 :             else if (tok2->str() == "}") {
     984         [ +  + ]:       2835 :                 if (indentlevel == 0) {
     985         [ +  + ]:        180 :                     if (_settings->inconclusive)
     986                 :         45 :                         inconclusive = true;
     987                 :            :                     else
     988                 :        135 :                         break;
     989                 :            :                 }
     990                 :       2700 :                 --indentlevel;
     991                 :            : 
     992                 :            :                 // calling exit function?
     993                 :       2700 :                 bool unknown = false;
     994         [ +  + ]:       2700 :                 if (_tokenizer->IsScopeNoReturn(tok2, &unknown)) {
     995 [ +  - ][ +  - ]:         45 :                     if (_settings->inconclusive && unknown)
     996                 :         45 :                         inconclusive = true;
     997                 :            :                     else
     998                 :          0 :                         break;
     999                 :            :                 }
    1000                 :            : 
    1001         [ +  + ]:       2700 :                 if (indentlevel <= 0) {
    1002                 :            :                     // skip all "else" blocks because they are not executed in this execution path
    1003         [ +  + ]:       2655 :                     while (Token::simpleMatch(tok2, "} else if ("))
    1004                 :         45 :                         tok2 = tok2->linkAt(3)->linkAt(1);
    1005         [ +  + ]:       2610 :                     if (Token::simpleMatch(tok2, "} else {"))
    1006                 :         45 :                         tok2 = tok2->linkAt(2);
    1007                 :            :                 }
    1008                 :            :             }
    1009                 :            : 
    1010 [ +  + ][ +  + ]:      20790 :             if (tok2->str() == "return" || tok2->str() == "throw") {
                 [ +  + ]
    1011                 :        810 :                 bool unknown = _settings->inconclusive;
    1012 [ +  - ][ +  + ]:       2520 :                 for (; tok2 && tok2->str() != ";"; tok2 = tok2->next()) {
                 [ +  + ]
    1013         [ +  + ]:       1755 :                     if (tok2->varId() == varid) {
    1014         [ +  + ]:        180 :                         if (CheckNullPointer::isPointerDeRef(tok2, unknown))
    1015                 :        135 :                             nullPointerError(tok2, pointerName, vartok, inconclusive);
    1016         [ -  + ]:         45 :                         else if (unknown)
    1017                 :          0 :                             nullPointerError(tok2, pointerName, vartok, true);
    1018         [ +  + ]:        180 :                         if (Token::Match(tok2, "%var% ?"))
    1019                 :         45 :                             break;
    1020                 :            :                     }
    1021                 :            :                 }
    1022                 :        810 :                 break;
    1023                 :            :             }
    1024                 :            : 
    1025                 :            :             // Bailout for "if".
    1026         [ +  + ]:      19980 :             if (tok2->str() == "if") {
    1027         [ +  + ]:        315 :                 if (_settings->inconclusive)
    1028                 :         90 :                     inconclusive = true;
    1029                 :            :                 else
    1030                 :        225 :                     break;
    1031                 :            :             }
    1032                 :            : 
    1033         [ +  + ]:      19755 :             if (Token::Match(tok2, "goto|continue|break|switch|for"))
    1034                 :        315 :                 break;
    1035                 :            : 
    1036                 :            :             // parameters to sizeof are not dereferenced
    1037         [ +  + ]:      19440 :             if (Token::Match(tok2, "decltype|sizeof")) {
    1038         [ +  + ]:        180 :                 if (tok2->strAt(1) != "(")
    1039                 :         45 :                     tok2 = tok2->next();
    1040                 :            :                 else
    1041                 :        135 :                     tok2 = tok2->next()->link();
    1042                 :        180 :                 continue;
    1043                 :            :             }
    1044                 :            : 
    1045                 :            :             // function call, check if pointer is dereferenced
    1046 [ +  + ][ +  + ]:      19260 :             if (Token::Match(tok2, "%var% (") && !Token::Match(tok2, "if|while")) {
                 [ +  + ]
    1047                 :        675 :                 std::list<const Token *> vars;
    1048         [ +  - ]:        675 :                 parseFunctionCall(*tok2, vars, 0);
    1049 [ +  - ][ +  - ]:        720 :                 for (std::list<const Token *>::const_iterator it = vars.begin(); it != vars.end(); ++it) {
                 [ +  + ]
    1050 [ +  - ][ +  + ]:        135 :                     if (Token::Match(*it, "%varid% [,)]", varid)) {
    1051         [ +  - ]:         90 :                         nullPointerError(*it, pointerName, vartok, inconclusive);
    1052                 :         90 :                         break;
    1053                 :            :                     }
    1054                 :        675 :                 }
    1055                 :            :             }
    1056                 :            : 
    1057                 :            :             // calling unknown function (abort/init)..
    1058   [ +  +  +  +  :      19125 :             else if (Token::simpleMatch(tok2, ") ;") &&
           +  - ][ +  + ]
    1059                 :        495 :                      (Token::Match(tok2->link()->tokAt(-2), "[;{}.] %var% (") ||
    1060                 :         45 :                       Token::Match(tok2->link()->tokAt(-5), "[;{}] ( * %var% ) ("))) {
    1061                 :            :                 // noreturn function?
    1062                 :        495 :                 bool unknown = false;
    1063         [ +  + ]:        495 :                 if (_tokenizer->IsScopeNoReturn(tok2->tokAt(2), &unknown)) {
    1064 [ +  + ][ +  + ]:        405 :                     if (!unknown || !_settings->inconclusive) {
    1065                 :        270 :                         break;
    1066                 :            :                     }
    1067                 :        135 :                     inconclusive = _settings->inconclusive;
    1068                 :            :                 }
    1069                 :            : 
    1070                 :            :                 // init function (global variables)
    1071 [ +  - ][ +  - ]:        225 :                 if (!var || !(var->isLocal() || var->isArgument()))
         [ +  + ][ +  + ]
    1072                 :         45 :                     break;
    1073                 :            :             }
    1074                 :            : 
    1075         [ +  + ]:      18945 :             if (tok2->varId() == varid) {
    1076                 :            :                 // unknown: this is set to true by isPointerDeRef if
    1077                 :            :                 //          the function fails to determine if there
    1078                 :            :                 //          is a dereference or not
    1079                 :       1440 :                 bool unknown = _settings->inconclusive;
    1080                 :            : 
    1081         [ +  - ]:       1440 :                 if (Token::Match(tok2->previous(), "[;{}=] %var% = 0 ;"))
    1082                 :            :                     ;
    1083                 :            : 
    1084         [ +  + ]:       1440 :                 else if (CheckNullPointer::isPointerDeRef(tok2, unknown))
    1085                 :        720 :                     nullPointerError(tok2, pointerName, vartok, inconclusive);
    1086                 :            : 
    1087 [ +  + ][ +  + ]:        720 :                 else if (unknown && _settings->inconclusive)
    1088                 :        135 :                     nullPointerError(tok2, pointerName, vartok, true);
    1089                 :            : 
    1090                 :            :                 else
    1091                 :       1440 :                     break;
    1092                 :            :             }
    1093                 :            :         }
    1094                 :            :     }
    1095                 :      11655 : }
    1096                 :            : 
    1097                 :            : 
    1098                 :      12391 : void CheckNullPointer::nullPointer()
    1099                 :            : {
    1100                 :      12391 :     nullPointerLinkedList();
    1101                 :            : 
    1102 [ +  - ][ +  - ]:      12391 :     if (_settings->isEnabled("warning")) {
         [ +  - ][ +  + ]
    1103                 :      11655 :         nullPointerStructByDeRefAndChec();
    1104                 :      11655 :         nullPointerByDeRefAndChec();
    1105                 :      11655 :         nullPointerByCheckAndDeRef();
    1106                 :            :     }
    1107                 :            : 
    1108                 :      12391 :     nullPointerDefaultArgument();
    1109                 :      12391 : }
    1110                 :            : 
    1111                 :            : /** Dereferencing null constant (simplified token list) */
    1112                 :      12391 : void CheckNullPointer::nullConstantDereference()
    1113                 :            : {
    1114                 :      12391 :     const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
    1115                 :            : 
    1116                 :      12391 :     const std::size_t functions = symbolDatabase->functionScopes.size();
    1117         [ +  + ]:      25052 :     for (std::size_t i = 0; i < functions; ++i) {
    1118                 :      12661 :         const Scope * scope = symbolDatabase->functionScopes[i];
    1119 [ +  - ][ -  + ]:      12661 :         if (scope->function == 0 || !scope->function->hasBody) // We only look for functions with a body
    1120                 :          0 :             continue;
    1121                 :            : 
    1122                 :      12661 :         const Token *tok = scope->classStart;
    1123                 :            : 
    1124 [ +  - ][ +  + ]:      12661 :         if (scope->function && (scope->function->type == Function::eConstructor || scope->function->type == Function::eCopyConstructor))
                 [ -  + ]
    1125                 :         90 :             tok = scope->function->token; // Check initialization list
    1126                 :            : 
    1127         [ +  + ]:     268235 :         for (; tok != scope->classEnd; tok = tok->next()) {
    1128         [ +  + ]:     255574 :             if (Token::Match(tok, "sizeof|decltype|typeid ("))
    1129                 :        585 :                 tok = tok->next()->link();
    1130                 :            : 
    1131         [ +  + ]:     254989 :             else if (Token::simpleMatch(tok, "* 0")) {
    1132 [ +  + ][ +  - ]:        450 :                 if (Token::Match(tok->previous(), "return|throw|;|{|}|:|[|(|,") || tok->previous()->isOp()) {
                 [ +  - ]
    1133                 :        450 :                     nullPointerError(tok);
    1134                 :            :                 }
    1135                 :            :             }
    1136                 :            : 
    1137 [ +  + ][ -  + ]:     254539 :             else if (Token::Match(tok, "0 [") && (tok->previous()->str() != "&" || !Token::Match(tok->next()->link()->next(), "[.(]")))
         [ #  # ][ +  + ]
    1138                 :         90 :                 nullPointerError(tok);
    1139                 :            : 
    1140 [ +  + ][ +  + ]:     254449 :             else if (Token::Match(tok->previous(), "!!. %var% (") && (tok->previous()->str() != "::" || tok->strAt(-2) == "std")) {
         [ +  + ][ +  + ]
    1141 [ +  + ][ +  + ]:      16371 :                 if (Token::simpleMatch(tok->tokAt(2), "0 )") && tok->varId()) { // constructor call
                 [ +  + ]
    1142                 :        135 :                     const Variable *var = tok->variable();
    1143 [ +  - ][ +  - ]:        135 :                     if (var && !var->isPointer() && !var->isArray() && Token::Match(var->typeStartToken(), "std :: string|wstring !!::"))
         [ +  - ][ +  - ]
                 [ +  - ]
    1144                 :        135 :                         nullPointerError(tok);
    1145                 :            :                 } else { // function call
    1146                 :      16236 :                     std::list<const Token *> var;
    1147         [ +  - ]:      16236 :                     parseFunctionCall(*tok, var, 0);
    1148                 :            : 
    1149                 :            :                     // is one of the var items a NULL pointer?
    1150 [ +  - ][ +  - ]:      18126 :                     for (std::list<const Token *>::const_iterator it = var.begin(); it != var.end(); ++it) {
                 [ +  + ]
    1151 [ +  - ][ +  + ]:       1890 :                         if (Token::Match(*it, "0 [,)]")) {
    1152         [ +  - ]:        630 :                             nullPointerError(*it);
    1153                 :            :                         }
    1154                 :      16236 :                     }
    1155                 :            :                 }
    1156         [ +  + ]:     238078 :             } else if (Token::Match(tok, "std :: string|wstring ( 0 )"))
    1157                 :         45 :                 nullPointerError(tok);
    1158                 :            : 
    1159         [ -  + ]:     238033 :             else if (Token::simpleMatch(tok->previous(), ">> 0")) { // Only checking input stream operations is safe here, because otherwise 0 can be an integer as well
    1160                 :          0 :                 const Token* tok2 = tok->previous(); // Find start of statement
    1161         [ #  # ]:          0 :                 for (; tok2; tok2 = tok2->previous()) {
    1162         [ #  # ]:          0 :                     if (Token::Match(tok2->previous(), ";|{|}|:"))
    1163                 :          0 :                         break;
    1164                 :            :                 }
    1165         [ #  # ]:          0 :                 if (Token::simpleMatch(tok2, "std :: cin"))
    1166                 :          0 :                     nullPointerError(tok);
    1167 [ #  # ][ #  # ]:          0 :                 if (tok2 && tok2->varId() != 0) {
                 [ #  # ]
    1168                 :          0 :                     const Variable *var = tok2->variable();
    1169 [ #  # ][ #  # ]:          0 :                     if (var && Token::Match(var->typeStartToken(), "std :: istream|ifstream|istringstream|wistringstream|stringstream|wstringstream|fstream|iostream"))
                 [ #  # ]
    1170                 :          0 :                         nullPointerError(tok);
    1171                 :            :                 }
    1172                 :            :             }
    1173                 :            : 
    1174                 :     255574 :             const Variable *ovar = 0;
    1175         [ +  + ]:     255574 :             if (Token::Match(tok, "0 ==|!= %var%"))
    1176                 :         45 :                 ovar = tok->tokAt(2)->variable();
    1177         [ +  + ]:     255529 :             else if (Token::Match(tok, "%var% ==|!= 0"))
    1178                 :         45 :                 ovar = tok->variable();
    1179         [ +  + ]:     255484 :             else if (Token::Match(tok, "%var% =|+ 0 )|]|,|;|+"))
    1180                 :       5940 :                 ovar = tok->variable();
    1181 [ +  + ][ +  + ]:     255574 :             if (ovar && !ovar->isPointer() && !ovar->isArray() && Token::Match(ovar->typeStartToken(), "std :: string|wstring !!::"))
         [ +  - ][ +  + ]
                 [ +  + ]
    1182                 :        135 :                 nullPointerError(tok);
    1183                 :            :         }
    1184                 :            :     }
    1185                 :      12391 : }
    1186                 :            : 
    1187                 :            : 
    1188                 :            : /**
    1189                 :            : * @brief Does one part of the check for nullPointer().
    1190                 :            : * -# default argument that sets a pointer to 0
    1191                 :            : * -# dereference pointer
    1192                 :            : */
    1193                 :      12391 : void CheckNullPointer::nullPointerDefaultArgument()
    1194                 :            : {
    1195                 :      12391 :     const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
    1196                 :      12391 :     const std::size_t functions = symbolDatabase->functionScopes.size();
    1197         [ +  + ]:      25052 :     for (std::size_t i = 0; i < functions; ++i) {
    1198                 :      12661 :         const Scope * scope = symbolDatabase->functionScopes[i];
    1199 [ +  - ][ -  + ]:      12661 :         if (scope->function == 0 || !scope->function->hasBody) // We only look for functions with a body
    1200                 :          0 :             continue;
    1201                 :            : 
    1202                 :            :         // Scan the argument list for default arguments that are pointers and
    1203                 :            :         // which default to a NULL pointer if no argument is specified.
    1204                 :      12661 :         std::set<unsigned int> pointerArgs;
    1205         [ +  + ]:      50972 :         for (const Token *tok = scope->function->arg; tok != scope->function->arg->link(); tok = tok->next()) {
    1206                 :            : 
    1207 [ +  - ][ +  + ]:      38311 :             if (Token::Match(tok, "%var% = 0 ,|)") && tok->varId() != 0) {
         [ +  - ][ +  + ]
    1208                 :        675 :                 const Variable *var = tok->variable();
    1209 [ +  - ][ +  - ]:        675 :                 if (var && var->isPointer())
                 [ +  - ]
    1210         [ +  - ]:        675 :                     pointerArgs.insert(tok->varId());
    1211                 :            :             }
    1212                 :            :         }
    1213                 :            : 
    1214                 :            :         // Report an error if any of the default-NULL arguments are dereferenced
    1215 [ +  - ][ +  + ]:      12661 :         if (!pointerArgs.empty()) {
    1216                 :        675 :             bool unknown = _settings->inconclusive;
    1217         [ +  + ]:       7200 :             for (const Token *tok = scope->classStart; tok != scope->classEnd; tok = tok->next()) {
    1218                 :            :                 // If we encounter a possible NULL-pointer check, skip over its body
    1219 [ +  - ][ +  + ]:       6525 :                 if (Token::simpleMatch(tok, "if ( "))  {
    1220                 :        225 :                     bool dependsOnPointer = false;
    1221                 :        225 :                     const Token *endOfCondition = tok->next()->link();
    1222         [ -  + ]:        225 :                     if (!endOfCondition)
    1223                 :          0 :                         continue;
    1224                 :            : 
    1225                 :            :                     const Token *startOfIfBlock =
    1226 [ +  - ][ +  - ]:        225 :                         Token::simpleMatch(endOfCondition, ") {") ? endOfCondition->next() : NULL;
    1227         [ -  + ]:        225 :                     if (!startOfIfBlock)
    1228                 :          0 :                         continue;
    1229                 :            : 
    1230                 :            :                     // If this if() statement may return, it may be a null
    1231                 :            :                     // pointer check for the pointers referenced in its condition
    1232                 :        225 :                     const Token *endOfIf = startOfIfBlock->link();
    1233                 :            :                     bool isExitOrReturn =
    1234         [ +  - ]:        225 :                         Token::findmatch(startOfIfBlock, "exit|return", endOfIf) != NULL;
    1235                 :            : 
    1236         [ +  + ]:        945 :                     for (const Token *tok2 = tok->next(); tok2 != endOfCondition; tok2 = tok2->next()) {
    1237 [ +  + ][ +  + ]:        900 :                         if (tok2->isName() && tok2->varId() > 0 &&
         [ +  - ][ +  + ]
    1238         [ +  - ]:        180 :                             pointerArgs.count(tok2->varId()) > 0) {
    1239                 :            : 
    1240                 :            :                             // If the if() depends on a pointer and may return, stop
    1241                 :            :                             // considering that pointer because it may be a NULL-pointer
    1242                 :            :                             // check that returns if the pointer is NULL.
    1243         [ +  + ]:        180 :                             if (isExitOrReturn)
    1244         [ +  - ]:         45 :                                 pointerArgs.erase(tok2->varId());
    1245                 :            :                             else
    1246                 :        135 :                                 dependsOnPointer = true;
    1247                 :            :                         }
    1248                 :            :                     }
    1249 [ +  + ][ +  - ]:        225 :                     if (dependsOnPointer && endOfIf) {
    1250         [ +  + ]:       1710 :                         for (; tok != endOfIf; tok = tok->next()) {
    1251                 :            :                             // If a pointer is assigned a new value, stop considering it.
    1252 [ +  - ][ +  + ]:       1575 :                             if (Token::Match(tok, "%var% ="))
    1253         [ +  - ]:        135 :                                 pointerArgs.erase(tok->varId());
    1254                 :            :                         }
    1255                 :        135 :                         continue;
    1256                 :            :                     }
    1257                 :            :                 }
    1258                 :            : 
    1259 [ +  + ][ +  - ]:       6390 :                 if (tok->varId() == 0 || pointerArgs.count(tok->varId()) == 0)
         [ +  + ][ +  + ]
    1260                 :       5670 :                     continue;
    1261                 :            : 
    1262                 :            :                 // If a pointer is assigned a new value, stop considering it.
    1263 [ +  - ][ +  + ]:        720 :                 if (Token::Match(tok, "%var% ="))
    1264         [ +  - ]:        225 :                     pointerArgs.erase(tok->varId());
    1265                 :            : 
    1266                 :            :                 // If a pointer dereference is preceded by an && or ||,
    1267                 :            :                 // they serve as a sequence point so the dereference
    1268                 :            :                 // may not be executed.
    1269 [ +  - ][ +  + ]:       1980 :                 if (isPointerDeRef(tok, unknown) &&
         [ +  + ][ +  - ]
         [ +  + ][ +  + ]
                 [ +  + ]
    1270 [ +  - ][ +  - ]:        675 :                     tok->strAt(-1) != "&&" && tok->strAt(-1) != "||" &&
         [ +  - ][ +  - ]
    1271 [ +  - ][ +  - ]:        585 :                     tok->strAt(-2) != "&&" && tok->strAt(-2) != "||")
         [ +  - ][ +  - ]
    1272         [ +  - ]:        225 :                     nullPointerDefaultArgError(tok, tok->str());
    1273                 :            :             }
    1274                 :            :         }
    1275                 :      12661 :     }
    1276                 :      12391 : }
    1277                 :            : 
    1278                 :            : /// @addtogroup Checks
    1279                 :            : /// @{
    1280                 :            : 
    1281                 :            : 
    1282                 :            : /**
    1283                 :            :  * @brief %Check for null pointer usage (using ExecutionPath)
    1284                 :            :  */
    1285                 :            : 
    1286 [ +  - ][ -  + ]:     144337 : class Nullpointer : public ExecutionPath {
                 [ +  - ]
    1287                 :            : public:
    1288                 :            :     /** Startup constructor */
    1289         [ +  - ]:      12391 :     Nullpointer(Check *c, const SymbolDatabase* symbolDatabase_) : ExecutionPath(c, 0), symbolDatabase(symbolDatabase_), null(false) {
    1290                 :      12391 :     }
    1291                 :            : 
    1292                 :            : private:
    1293                 :            :     const SymbolDatabase* symbolDatabase;
    1294                 :            : 
    1295                 :            :     /** Create checking of specific variable: */
    1296                 :       4851 :     Nullpointer(Check *c, const unsigned int id, const std::string &name, const SymbolDatabase* symbolDatabase_)
    1297                 :            :         : ExecutionPath(c, id),
    1298                 :            :           symbolDatabase(symbolDatabase_),
    1299                 :            :           varname(name),
    1300         [ +  - ]:       4851 :           null(false) {
    1301                 :       4851 :     }
    1302                 :            : 
    1303                 :            :     /** Copy this check */
    1304                 :      40748 :     ExecutionPath *copy() {
    1305         [ +  - ]:      40748 :         return new Nullpointer(*this);
    1306                 :            :     }
    1307                 :            : 
    1308                 :            :     /** no implementation => compiler error if used by accident */
    1309                 :            :     void operator=(const Nullpointer &);
    1310                 :            : 
    1311                 :            :     /** is other execution path equal? */
    1312                 :        135 :     bool is_equal(const ExecutionPath *e) const {
    1313                 :        135 :         const Nullpointer *c = static_cast<const Nullpointer *>(e);
    1314 [ +  - ][ +  + ]:        135 :         return (varname == c->varname && null == c->null);
    1315                 :            :     }
    1316                 :            : 
    1317                 :            :     /** variable name for this check (empty => dummy check) */
    1318                 :            :     const std::string varname;
    1319                 :            : 
    1320                 :            :     /** is this variable null? */
    1321                 :            :     bool null;
    1322                 :            : 
    1323                 :            :     /** variable is set to null */
    1324                 :       2925 :     static void setnull(std::list<ExecutionPath *> &checks, const unsigned int varid) {
    1325                 :       2925 :         std::list<ExecutionPath *>::iterator it;
    1326         [ +  + ]:       8505 :         for (it = checks.begin(); it != checks.end(); ++it) {
    1327         [ -  + ]:       5580 :             Nullpointer *c = dynamic_cast<Nullpointer *>(*it);
    1328 [ +  - ][ +  + ]:       5580 :             if (c && c->varId == varid)
    1329                 :       2520 :                 c->null = true;
    1330                 :            :         }
    1331                 :       2925 :     }
    1332                 :            : 
    1333                 :            :     /**
    1334                 :            :      * Dereferencing variable. Check if it is safe (if the variable is null there's an error)
    1335                 :            :      * @param checks Checks
    1336                 :            :      * @param tok token where dereferencing happens
    1337                 :            :      */
    1338                 :      12195 :     static void dereference(std::list<ExecutionPath *> &checks, const Token *tok) {
    1339                 :      12195 :         const unsigned int varid(tok->varId());
    1340                 :            : 
    1341                 :      12195 :         std::list<ExecutionPath *>::iterator it;
    1342         [ +  + ]:      27000 :         for (it = checks.begin(); it != checks.end(); ++it) {
    1343         [ -  + ]:      14805 :             Nullpointer *c = dynamic_cast<Nullpointer *>(*it);
    1344 [ +  - ][ +  + ]:      14805 :             if (c && c->varId == varid && c->null) {
                 [ +  + ]
    1345 [ +  - ][ +  + ]:       7560 :                 for (const Token *tok2 = tok; tok2 && tok2->str() != ";"; tok2 = tok2->previous()) {
                 [ +  + ]
    1346                 :            :                     // Checking that pointer is not NULL
    1347         [ +  + ]:       6210 :                     if (Token::Match(tok2, "return|=|[|(|,|&& %varid% )| &&", varid))
    1348                 :         45 :                         return;
    1349         [ +  + ]:       6165 :                     if (Token::Match(tok2, "return|=|[|(|,|%oror% ! %varid% )| %oror%", varid))
    1350                 :         45 :                         return;
    1351                 :            :                 }
    1352                 :            : 
    1353         [ -  + ]:       1350 :                 CheckNullPointer *checkNullPointer = dynamic_cast<CheckNullPointer *>(c->owner);
    1354         [ +  - ]:       1350 :                 if (checkNullPointer) {
    1355                 :       1350 :                     checkNullPointer->nullPointerError(tok, c->varname);
    1356                 :       1350 :                     return;
    1357                 :            :                 }
    1358                 :            :             }
    1359                 :            :         }
    1360                 :            :     }
    1361                 :            : 
    1362                 :            :     /** parse tokens */
    1363                 :     169612 :     const Token *parse(const Token &tok, std::list<ExecutionPath *> &checks) const {
    1364         [ +  + ]:     169612 :         if (tok.varId() != 0) {
    1365                 :            :             // Pointer declaration declaration?
    1366                 :      30842 :             const Variable *var = tok.variable();
    1367 [ +  + ][ +  + ]:      30842 :             if (var && var->isPointer() && var->nameToken() == &tok)
         [ +  + ][ +  + ]
    1368         [ +  - ]:       4851 :                 checks.push_back(new Nullpointer(owner, var->varId(), var->name(), symbolDatabase));
    1369                 :            :         }
    1370                 :            : 
    1371         [ +  + ]:     169612 :         if (Token::simpleMatch(&tok, "try {")) {
    1372                 :            :             // Bail out all used variables
    1373                 :         90 :             const Token* tok2 = &tok;
    1374                 :         90 :             const Token* endtok = tok.linkAt(1);
    1375 [ +  - ][ +  + ]:        270 :             for (; tok2 && tok2 != endtok; tok2 = tok2->next()) {
                 [ +  + ]
    1376         [ -  + ]:        180 :                 if (tok2->varId())
    1377                 :          0 :                     bailOutVar(checks,tok2->varId());
    1378                 :            :             }
    1379                 :         90 :             return tok2;
    1380                 :            :         }
    1381                 :            : 
    1382         [ +  + ]:     169522 :         if (Token::Match(&tok, "%var% (")) {
    1383 [ +  + ][ +  + ]:       8496 :             if (tok.str() == "sizeof" || tok.str() == "typeid")
                 [ +  + ]
    1384                 :        405 :                 return tok.next()->link();
    1385                 :            : 
    1386                 :            :             // parse usage..
    1387                 :       8091 :             std::list<const Token *> var;
    1388         [ +  - ]:       8091 :             CheckNullPointer::parseFunctionCall(tok, var, 0);
    1389 [ +  - ][ +  - ]:       9936 :             for (std::list<const Token *>::const_iterator it = var.begin(); it != var.end(); ++it)
                 [ +  + ]
    1390         [ +  - ]:       9936 :                 dereference(checks, *it);
    1391                 :            :         }
    1392                 :            : 
    1393         [ -  + ]:     161026 :         else if (Token::simpleMatch(&tok, "( 0 &&"))
    1394                 :          0 :             return tok.link();
    1395                 :            : 
    1396         [ +  + ]:     169117 :         if (tok.varId() != 0) {
    1397                 :            :             // unknown: if isPointerDeRef fails to determine if there
    1398                 :            :             //          is a dereference this will be set to true.
    1399                 :      30842 :             bool unknown = owner->inconclusiveFlag();
    1400                 :      30842 :             bool deref = CheckNullPointer::isPointerDeRef(&tok, unknown);
    1401                 :            : 
    1402         [ +  + ]:      30842 :             if (deref)
    1403                 :       6750 :                 dereference(checks, &tok);
    1404 [ +  + ][ +  + ]:      24092 :             else if (unknown && owner->inconclusiveFlag())
                 [ +  + ]
    1405                 :       2565 :                 dereference(checks, &tok);
    1406         [ +  + ]:      30842 :             if (Token::Match(tok.previous(), "[;{}=] %var% = 0 ;"))
    1407                 :       2925 :                 setnull(checks, tok.varId());
    1408   [ +  +  +  +  :      71466 :             else if (!deref &&
          +  +  +  +  +  
              + ][ +  + ]
    1409                 :      28313 :                      (!tok.previous()->isOp() || tok.previous()->str() == "&") &&
    1410                 :      15236 :                      (!tok.next()->isConstOp() || tok.next()->str() == ">>"))
    1411                 :      13706 :                 bailOutVar(checks, tok.varId()); // If its possible that the pointers value changes, bail out.
    1412                 :            :         }
    1413                 :            : 
    1414         [ +  + ]:     138275 :         else if (tok.str() == "delete") {
    1415                 :        135 :             const Token *ret = tok.next();
    1416         [ +  + ]:        135 :             if (Token::simpleMatch(ret, "[ ]"))
    1417                 :         45 :                 ret = ret->tokAt(2);
    1418         [ +  - ]:        135 :             if (Token::Match(ret, "%var% ;"))
    1419                 :        135 :                 return ret->next();
    1420                 :            :         }
    1421                 :            : 
    1422         [ +  + ]:     138140 :         else if (tok.str() == "return") {
    1423                 :       2055 :             bool unknown = owner->inconclusiveFlag();
    1424                 :       2055 :             const Token* tok2 = &tok;
    1425 [ +  - ][ +  + ]:       8370 :             for (; tok2 && tok2->str() != ";"; tok2 = tok2->next()) {
                 [ +  + ]
    1426         [ +  + ]:       6450 :                 if (tok2->varId()) {
    1427 [ +  + ][ -  + ]:       1125 :                     if (CheckNullPointer::isPointerDeRef(tok2, unknown) || unknown)
                 [ +  + ]
    1428                 :        540 :                         dereference(checks, tok2);
    1429                 :            :                 }
    1430                 :            : 
    1431                 :            :                 // If return statement contains "?" then assume there
    1432                 :            :                 // is no dangours dereferencing later
    1433         [ +  + ]:       6450 :                 if (tok2->str() == "?") {
    1434 [ +  - ][ +  + ]:       1170 :                     while (tok2 && tok2->str() != ";")
                 [ +  + ]
    1435                 :       1035 :                         tok2 = tok2->next();
    1436                 :        135 :                     return tok2;
    1437                 :            :                 }
    1438                 :            :             }
    1439                 :            :         }
    1440                 :            : 
    1441                 :     169612 :         return &tok;
    1442                 :            :     }
    1443                 :            : 
    1444                 :            :     /** parse condition. @sa ExecutionPath::parseCondition */
    1445                 :       8145 :     bool parseCondition(const Token &tok, std::list<ExecutionPath *> &checks) {
    1446         [ +  - ]:      21465 :         for (const Token *tok2 = &tok; tok2; tok2 = tok2->next()) {
    1447 [ +  + ][ +  + ]:      21465 :             if (tok2->str() == "(" || tok2->str() == ")" || tok2->str() == "&&" || tok2->str() == "||" || tok2->str() == "?")
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
    1448                 :       8145 :                 break;
    1449                 :      13320 :             bool unknown = owner->inconclusiveFlag();
    1450 [ +  + ][ +  + ]:      13320 :             if (tok2->varId() && (CheckNullPointer::isPointerDeRef(tok2, unknown) || unknown))
         [ +  + ][ +  + ]
    1451                 :        405 :                 dereference(checks, tok2);
    1452                 :            :         }
    1453                 :            : 
    1454         [ +  + ]:       8145 :         if (Token::Match(&tok, "!| %var% (")) {
    1455                 :         90 :             std::list<const Token *> var;
    1456 [ +  - ][ +  + ]:         90 :             CheckNullPointer::parseFunctionCall(tok.str() == "!" ? *tok.next() : tok, var, 0);
                 [ +  - ]
    1457 [ +  - ][ +  - ]:        180 :             for (std::list<const Token *>::const_iterator it = var.begin(); it != var.end(); ++it)
                 [ +  + ]
    1458         [ +  - ]:        180 :                 dereference(checks, *it);
    1459                 :            :         }
    1460                 :            : 
    1461                 :       8145 :         return ExecutionPath::parseCondition(tok, checks);
    1462                 :            :     }
    1463                 :            : 
    1464                 :            : 
    1465                 :       1170 :     void parseLoopBody(const Token *tok, std::list<ExecutionPath *> &checks) const {
    1466         [ +  - ]:       8190 :         while (tok) {
    1467         [ +  + ]:       8190 :             if (Token::Match(tok, "{|}|return|goto|break|if"))
    1468                 :       1170 :                 return;
    1469                 :       7020 :             const Token *next = parse(*tok, checks);
    1470         [ +  - ]:       7020 :             if (next)
    1471                 :       7020 :                 tok = tok->next();
    1472                 :            :         }
    1473                 :            :     }
    1474                 :            : 
    1475                 :            : };
    1476                 :            : /// @}
    1477                 :            : 
    1478                 :            : 
    1479                 :      12391 : void CheckNullPointer::executionPaths()
    1480                 :            : {
    1481                 :            :     // Check for null pointer errors..
    1482                 :      12391 :     Nullpointer c(this, _tokenizer->getSymbolDatabase());
    1483         [ +  - ]:      12391 :     checkExecutionPaths(_tokenizer->getSymbolDatabase(), &c);
    1484                 :      12391 : }
    1485                 :            : 
    1486                 :       1485 : void CheckNullPointer::nullPointerError(const Token *tok)
    1487                 :            : {
    1488 [ +  - ][ +  - ]:       1485 :     reportError(tok, Severity::error, "nullPointer", "Null pointer dereference");
         [ +  - ][ +  - ]
                 [ +  - ]
    1489                 :       1485 : }
    1490                 :            : 
    1491                 :       1395 : void CheckNullPointer::nullPointerError(const Token *tok, const std::string &varname)
    1492                 :            : {
    1493 [ +  - ][ +  - ]:       1395 :     reportError(tok, Severity::error, "nullPointer", "Possible null pointer dereference: " + varname);
                 [ +  - ]
    1494                 :       1395 : }
    1495                 :            : 
    1496                 :       2565 : void CheckNullPointer::nullPointerError(const Token *tok, const std::string &varname, const Token* nullCheck, bool inconclusive)
    1497                 :            : {
    1498                 :       2565 :     std::list<const Token*> callstack;
    1499         [ +  - ]:       2565 :     callstack.push_back(tok);
    1500         [ +  - ]:       2565 :     callstack.push_back(nullCheck);
    1501 [ +  - ][ +  - ]:       2565 :     const std::string errmsg("Possible null pointer dereference: " + varname + " - otherwise it is redundant to check it against null.");
                 [ +  - ]
    1502 [ +  - ][ +  - ]:       2565 :     reportError(callstack, Severity::error, "nullPointer", errmsg, inconclusive);
         [ +  - ][ +  - ]
    1503                 :       2565 : }
    1504                 :            : 
    1505                 :        225 : void CheckNullPointer::nullPointerDefaultArgError(const Token *tok, const std::string &varname)
    1506                 :            : {
    1507 [ +  - ][ +  - ]:        225 :     reportError(tok, Severity::warning, "nullPointer", "Possible null pointer dereference if the default parameter value is used: " + varname);
                 [ +  - ]
    1508 [ +  - ][ +  - ]:        360 : }

Generated by: LCOV version 1.9