Cppcheck
checkboost.cpp
Go to the documentation of this file.
1 /*
2  * Cppcheck - A tool for static C/C++ code analysis
3  * Copyright (C) 2007-2023 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 #include "checkboost.h"
20 
21 #include "errortypes.h"
22 #include "symboldatabase.h"
23 #include "token.h"
24 
25 #include <vector>
26 
27 // Register this check class (by creating a static instance of it)
28 namespace {
29  CheckBoost instance;
30 }
31 
32 static const CWE CWE664(664);
33 
35 {
36  logChecker("CheckBoost::checkBoostForeachModification");
37  const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase();
38  for (const Scope * scope : symbolDatabase->functionScopes) {
39  for (const Token *tok = scope->bodyStart->next(); tok && tok != scope->bodyEnd; tok = tok->next()) {
40  if (!Token::simpleMatch(tok, "BOOST_FOREACH ("))
41  continue;
42 
43  const Token *containerTok = tok->next()->link()->previous();
44  if (!Token::Match(containerTok, "%var% ) {"))
45  continue;
46 
47  const Token *tok2 = containerTok->tokAt(2);
48  const Token *end = tok2->link();
49  for (; tok2 != end; tok2 = tok2->next()) {
50  if (Token::Match(tok2, "%varid% . insert|erase|push_back|push_front|pop_front|pop_back|clear|swap|resize|assign|merge|remove|remove_if|reverse|sort|splice|unique|pop|push", containerTok->varId())) {
51  const Token* nextStatement = Token::findsimplematch(tok2->linkAt(3), ";", end);
52  if (!Token::Match(nextStatement, "; break|return|throw"))
53  boostForeachError(tok2);
54  break;
55  }
56  }
57  }
58  }
59 }
60 
62 {
63  reportError(tok, Severity::error, "boostForeachError",
64  "BOOST_FOREACH caches the end() iterator. It's undefined behavior if you modify the container inside.", CWE664, Certainty::normal
65  );
66 }
static const CWE CWE664(664)
Check Boost usage
Definition: checkboost.h:40
void checkBoostForeachModification()
Check for container modification while using the BOOST_FOREACH macro
Definition: checkboost.cpp:34
void boostForeachError(const Token *tok)
Definition: checkboost.cpp:61
void reportError(const Token *tok, const Severity severity, const std::string &id, const std::string &msg)
report an error
Definition: check.h:138
const Tokenizer *const mTokenizer
Definition: check.h:133
void logChecker(const char id[])
log checker
Definition: check.cpp:129
const Token * bodyStart
'{' token
const Token * bodyEnd
'}' token
std::vector< const Scope * > functionScopes
Fast access to function scopes.
The token list that the TokenList generates is a linked-list of this class.
Definition: token.h:150
static bool Match(const Token *tok, const char pattern[], nonneg int varid=0)
Match given token (or list of tokens) to a pattern list.
Definition: token.cpp:722
nonneg int varId() const
Definition: token.h:870
static const Token * findsimplematch(const Token *const startTok, const char(&pattern)[count])
Definition: token.h:763
const Token * tokAt(int index) const
Definition: token.cpp:427
void link(Token *linkToToken)
Create link to given token.
Definition: token.h:1015
const Token * linkAt(int index) const
Definition: token.cpp:447
Token * next()
Definition: token.h:830
static bool simpleMatch(const Token *tok, const char(&pattern)[count])
Match given token (or list of tokens) to a pattern list.
Definition: token.h:252
const SymbolDatabase * getSymbolDatabase() const
Definition: tokenize.h:563
@ error
Programming error.