MCPcopy Create free account
hub / github.com/cppcheck-opensource/cppcheck / checkDereferenceInvalidIterator

Method checkDereferenceInvalidIterator

lib/checkstl.cpp:2417–2478  ·  view source on GitHub ↗

Check for iterators being dereferenced before being checked for validity. E.g. if (*i && i != str.end()) { }

Source from the content-addressed store, hash-verified

2415// Check for iterators being dereferenced before being checked for validity.
2416// E.g. if (*i && i != str.end()) { }
2417void CheckStlImpl::checkDereferenceInvalidIterator()
2418{
2419 if (!mSettings.severity.isEnabled(Severity::warning))
2420 return;
2421
2422 logChecker("CheckStl::checkDereferenceInvalidIterator"); // warning
2423
2424 // Iterate over "if", "while", and "for" conditions where there may
2425 // be an iterator that is dereferenced before being checked for validity.
2426 for (const Scope &scope : mTokenizer->getSymbolDatabase()->scopeList) {
2427 if (!(scope.type == ScopeType::eIf || scope.isLoopScope()))
2428 continue;
2429
2430 const Token* const tok = scope.classDef;
2431 const Token* startOfCondition = tok->next();
2432 if (scope.type == ScopeType::eDo)
2433 startOfCondition = startOfCondition->link()->tokAt(2);
2434 if (!startOfCondition) // ticket #6626 invalid code
2435 continue;
2436 const Token* endOfCondition = startOfCondition->link();
2437 if (!endOfCondition)
2438 continue;
2439
2440 // For "for" loops, only search between the two semicolons
2441 if (scope.type == ScopeType::eFor) {
2442 startOfCondition = Token::findsimplematch(tok->tokAt(2), ";", endOfCondition);
2443 if (!startOfCondition)
2444 continue;
2445 endOfCondition = Token::findsimplematch(startOfCondition->next(), ";", endOfCondition);
2446 if (!endOfCondition)
2447 continue;
2448 }
2449
2450 // Only consider conditions composed of all "&&" terms and
2451 // conditions composed of all "||" terms
2452 const bool isOrExpression =
2453 Token::findsimplematch(startOfCondition, "||", endOfCondition) != nullptr;
2454 const bool isAndExpression =
2455 Token::findsimplematch(startOfCondition, "&&", endOfCondition) != nullptr;
2456
2457 // Look for a check of the validity of an iterator
2458 const Token* validityCheckTok = nullptr;
2459 if (!isOrExpression && isAndExpression) {
2460 validityCheckTok =
2461 Token::findmatch(startOfCondition, "&& %var% != %name% . end|rend|cend|crend ( )", endOfCondition);
2462 } else if (isOrExpression && !isAndExpression) {
2463 validityCheckTok =
2464 Token::findmatch(startOfCondition, "%oror% %var% == %name% . end|rend|cend|crend ( )", endOfCondition);
2465 }
2466
2467 if (!validityCheckTok)
2468 continue;
2469 const int iteratorVarId = validityCheckTok->next()->varId();
2470
2471 // If the iterator dereference is to the left of the check for
2472 // the iterator's validity, report an error.
2473 const Token* const dereferenceTok =
2474 Token::findmatch(startOfCondition, "* %varid%", validityCheckTok, iteratorVarId);

Callers 1

runChecksMethod · 0.80

Calls 4

findsimplematchFunction · 0.85
nextMethod · 0.80
isEnabledMethod · 0.45
tokAtMethod · 0.45

Tested by

no test coverage detected