| 285 | } |
| 286 | |
| 287 | void CheckBufferOverrunImpl::arrayIndex() |
| 288 | { |
| 289 | logChecker("CheckBufferOverrun::arrayIndex"); |
| 290 | |
| 291 | for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { |
| 292 | if (tok->str() != "[") |
| 293 | continue; |
| 294 | const Token *array = tok->astOperand1(); |
| 295 | while (Token::Match(array, ".|::")) |
| 296 | array = array->astOperand2(); |
| 297 | if (!array || ((!array->variable() || array->variable()->nameToken() == array) && array->tokType() != Token::eString)) |
| 298 | continue; |
| 299 | if (!array->scope()->isExecutable()) { |
| 300 | // LHS in non-executable scope => This is just a definition |
| 301 | const Token *parent = tok; |
| 302 | while (parent && !Token::simpleMatch(parent->astParent(), "=")) |
| 303 | parent = parent->astParent(); |
| 304 | if (!parent || parent == parent->astParent()->astOperand1()) |
| 305 | continue; |
| 306 | } |
| 307 | |
| 308 | if (astIsContainer(array)) |
| 309 | continue; |
| 310 | |
| 311 | std::vector<const Token *> indexTokens; |
| 312 | for (const Token *tok2 = tok; tok2 && tok2->str() == "["; tok2 = tok2->link()->next()) { |
| 313 | if (!tok2->astOperand2()) { |
| 314 | indexTokens.clear(); |
| 315 | break; |
| 316 | } |
| 317 | indexTokens.emplace_back(tok2->astOperand2()); |
| 318 | } |
| 319 | if (indexTokens.empty()) |
| 320 | continue; |
| 321 | |
| 322 | std::vector<Dimension> dimensions; |
| 323 | ErrorPath errorPath; |
| 324 | bool mightBeLarger = false; |
| 325 | MathLib::bigint path = 0; |
| 326 | if (!getDimensionsEtc(tok->astOperand1(), mSettings, dimensions, errorPath, mightBeLarger, path)) |
| 327 | continue; |
| 328 | |
| 329 | const Variable* const var = array->variable(); |
| 330 | if (var && var->isArgument() && var->scope()) { |
| 331 | const Token* changeTok = var->scope()->bodyStart; |
| 332 | bool isChanged = false; |
| 333 | while ((changeTok = findVariableChanged(changeTok->next(), var->scope()->bodyEnd, /*indirect*/ 0, var->declarationId(), |
| 334 | /*globalvar*/ false, mSettings))) { |
| 335 | if (!Token::simpleMatch(changeTok->astParent(), "[")) { |
| 336 | isChanged = true; |
| 337 | break; |
| 338 | } |
| 339 | } |
| 340 | if (isChanged) |
| 341 | continue; |
| 342 | } |
| 343 | |
| 344 | // Positive index |
no test coverage detected