| 111 | } |
| 112 | |
| 113 | void CheckSizeofImpl::checkSizeofForPointerSize() |
| 114 | { |
| 115 | if (!mSettings.severity.isEnabled(Severity::warning)) |
| 116 | return; |
| 117 | |
| 118 | logChecker("CheckSizeof::checkSizeofForPointerSize"); // warning |
| 119 | |
| 120 | const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); |
| 121 | for (const Scope * scope : symbolDatabase->functionScopes) { |
| 122 | for (const Token* tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) { |
| 123 | const Token* tokSize; |
| 124 | const Token* tokFunc; |
| 125 | const Token *variable = nullptr; |
| 126 | const Token *variable2 = nullptr; |
| 127 | |
| 128 | // Find any function that may use sizeof on a pointer |
| 129 | // Once leaving those tests, it is mandatory to have: |
| 130 | // - variable matching the used pointer |
| 131 | // - tokVar pointing on the argument where sizeof may be used |
| 132 | if (Token::Match(tok->tokAt(2), "%name% (") && mSettings.library.getAllocFuncInfo(tok->tokAt(2))) { |
| 133 | if (Token::Match(tok, "%var% =")) |
| 134 | variable = tok; |
| 135 | else if (tok->strAt(1) == ")" && Token::Match(tok->linkAt(1)->tokAt(-2), "%var% =")) |
| 136 | variable = tok->linkAt(1)->tokAt(-2); |
| 137 | else if (tok->link() && Token::Match(tok, "> ( %name% (") && Token::Match(tok->link()->tokAt(-3), "%var% =")) |
| 138 | variable = tok->link()->tokAt(-3); |
| 139 | tokSize = tok->tokAt(4); |
| 140 | tokFunc = tok->tokAt(2); |
| 141 | } else if (Token::simpleMatch(tok, "memset (") && tok->strAt(-1) != ".") { |
| 142 | variable = tok->tokAt(2); |
| 143 | tokSize = variable->nextArgument(); |
| 144 | if (tokSize) |
| 145 | tokSize = tokSize->nextArgument(); |
| 146 | tokFunc = tok; |
| 147 | } else if (Token::Match(tok, "memcpy|memcmp|memmove|strncpy|strncmp|strncat (") && tok->strAt(-1) != ".") { |
| 148 | variable = tok->tokAt(2); |
| 149 | variable2 = variable->nextArgument(); |
| 150 | if (!variable2) |
| 151 | continue; |
| 152 | tokSize = variable2->nextArgument(); |
| 153 | tokFunc = tok; |
| 154 | } else { |
| 155 | continue; |
| 156 | } |
| 157 | |
| 158 | if (tokSize && tokFunc->str() == "calloc") |
| 159 | tokSize = tokSize->nextArgument(); |
| 160 | |
| 161 | if (tokSize) { |
| 162 | const Token * const paramsListEndTok = tokFunc->linkAt(1); |
| 163 | for (const Token* tok2 = tokSize; tok2 != paramsListEndTok; tok2 = tok2->next()) { |
| 164 | if (Token::simpleMatch(tok2, "/ sizeof")) { |
| 165 | // Allow division with sizeof(char) |
| 166 | if (Token::simpleMatch(tok2->next(), "sizeof (")) { |
| 167 | const Token *sztok = tok2->tokAt(2)->astOperand2(); |
| 168 | const ValueType *vt = ((sztok != nullptr) ? sztok->valueType() : nullptr); |
| 169 | if (vt && vt->type == ValueType::CHAR && vt->pointer == 0) |
| 170 | continue; |
no test coverage detected