| 699 | //--------------------------------------------------------------------------- |
| 700 | |
| 701 | void CheckBufferOverrunImpl::arrayIndexThenCheck() |
| 702 | { |
| 703 | if (!mSettings.severity.isEnabled(Severity::style)) |
| 704 | return; |
| 705 | |
| 706 | logChecker("CheckBufferOverrun::arrayIndexThenCheck"); // style |
| 707 | |
| 708 | const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); |
| 709 | for (const Scope * const scope : symbolDatabase->functionScopes) { |
| 710 | for (const Token *tok = scope->bodyStart; tok && tok != scope->bodyEnd; tok = tok->next()) { |
| 711 | if (Token::simpleMatch(tok, "sizeof (")) { |
| 712 | tok = tok->linkAt(1); |
| 713 | continue; |
| 714 | } |
| 715 | |
| 716 | if (Token::Match(tok, "%name% [ %var% ]")) { |
| 717 | tok = tok->next(); |
| 718 | |
| 719 | const int indexID = tok->next()->varId(); |
| 720 | const std::string& indexName(tok->strAt(1)); |
| 721 | |
| 722 | // Iterate AST upwards |
| 723 | const Token* tok2 = tok; |
| 724 | const Token* tok3 = tok2; |
| 725 | while (tok2->astParent() && tok2->tokType() != Token::eLogicalOp && tok2->str() != "?") { |
| 726 | tok3 = tok2; |
| 727 | tok2 = tok2->astParent(); |
| 728 | } |
| 729 | |
| 730 | // Ensure that we ended at a logical operator and that we came from its left side |
| 731 | if (tok2->tokType() != Token::eLogicalOp || tok2->astOperand1() != tok3) |
| 732 | continue; |
| 733 | |
| 734 | // check if array index is ok |
| 735 | // statement can be closed in parentheses, so "(| " is using |
| 736 | if (Token::Match(tok2, "&& (| %varid% <|<=", indexID)) |
| 737 | arrayIndexThenCheckError(tok, indexName); |
| 738 | else if (Token::Match(tok2, "&& (| %any% >|>= %varid% !!+", indexID)) |
| 739 | arrayIndexThenCheckError(tok, indexName); |
| 740 | } |
| 741 | } |
| 742 | } |
| 743 | } |
| 744 | |
| 745 | void CheckBufferOverrunImpl::arrayIndexThenCheckError(const Token *tok, const std::string &indexName) |
| 746 | { |
no test coverage detected