Cppcheck
check.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 //---------------------------------------------------------------------------
20 
21 #include "check.h"
22 
23 #include "errorlogger.h"
24 #include "settings.h"
25 #include "token.h"
26 #include "tokenize.h"
27 #include "vfvalue.h"
28 
29 #include <algorithm>
30 #include <cctype>
31 #include <iostream>
32 #include <stdexcept>
33 #include <utility>
34 
35 //---------------------------------------------------------------------------
36 
37 Check::Check(const std::string &aname)
38  : mName(aname)
39 {
40  {
41  const auto it = std::find_if(instances().begin(), instances().end(), [&](const Check *i) {
42  return i->name() == aname;
43  });
44  if (it != instances().end())
45  throw std::runtime_error("'" + aname + "' instance already exists");
46  }
47 
48  // make sure the instances are sorted
49  const auto it = std::find_if(instances().begin(), instances().end(), [&](const Check* i) {
50  return i->name() > aname;
51  });
52  if (it == instances().end())
53  instances().push_back(this);
54  else
55  instances().insert(it, this);
56 }
57 
59 {
60  std::cout << errmsg.toXML() << std::endl;
61 }
62 
63 
64 void Check::reportError(const std::list<const Token *> &callstack, Severity severity, const std::string &id, const std::string &msg, const CWE &cwe, Certainty certainty)
65 {
66  const ErrorMessage errmsg(callstack, mTokenizer ? &mTokenizer->list : nullptr, severity, id, msg, cwe, certainty);
67  if (mErrorLogger)
68  mErrorLogger->reportErr(errmsg);
69  else
70  writeToErrorList(errmsg);
71 }
72 
73 void Check::reportError(const ErrorPath &errorPath, Severity severity, const char id[], const std::string &msg, const CWE &cwe, Certainty certainty)
74 {
75  const ErrorMessage errmsg(errorPath, mTokenizer ? &mTokenizer->list : nullptr, severity, id, msg, cwe, certainty);
76  if (mErrorLogger)
77  mErrorLogger->reportErr(errmsg);
78  else
79  writeToErrorList(errmsg);
80 }
81 
82 bool Check::wrongData(const Token *tok, const char *str)
83 {
84  if (mSettings->daca)
85  reportError(tok, Severity::debug, "DacaWrongData", "Wrong data detected by condition " + std::string(str));
86  return true;
87 }
88 
89 std::list<Check *> &Check::instances()
90 {
91 #ifdef __SVR4
92  // Under Solaris, destructors are called in wrong order which causes a segmentation fault.
93  // This fix ensures pointer remains valid and reachable until program terminates.
94  static std::list<Check *> *_instances= new std::list<Check *>;
95  return *_instances;
96 #else
97  static std::list<Check *> _instances;
98  return _instances;
99 #endif
100 }
101 
102 std::string Check::getMessageId(const ValueFlow::Value &value, const char id[])
103 {
104  if (value.condition != nullptr)
105  return id + std::string("Cond");
106  if (value.safe)
107  return std::string("safe") + (char)std::toupper(id[0]) + (id + 1);
108  return id;
109 }
110 
111 ErrorPath Check::getErrorPath(const Token* errtok, const ValueFlow::Value* value, std::string bug) const
112 {
113  ErrorPath errorPath;
114  if (!value) {
115  errorPath.emplace_back(errtok, std::move(bug));
116  } else if (mSettings->verbose || mSettings->xml || !mSettings->templateLocation.empty()) {
117  errorPath = value->errorPath;
118  errorPath.emplace_back(errtok, std::move(bug));
119  } else {
120  if (value->condition)
121  errorPath.emplace_back(value->condition, "condition '" + value->condition->expressionString() + "'");
122  //else if (!value->isKnown() || value->defaultArg)
123  // errorPath = value->callstack;
124  errorPath.emplace_back(errtok, std::move(bug));
125  }
126  return errorPath;
127 }
128 
129 void Check::logChecker(const char id[])
130 {
131  reportError(nullptr, Severity::internal, "logChecker", id);
132 }
133 
Interface class that cppcheck uses to communicate with the checks.
Definition: check.h:59
static std::list< Check * > & instances()
List of registered check classes.
Definition: check.cpp:89
Check(const std::string &aname)
This constructor is used when registering the CheckClass.
Definition: check.cpp:37
void reportError(const Token *tok, const Severity severity, const std::string &id, const std::string &msg)
report an error
Definition: check.h:140
const Settings *const mSettings
Definition: check.h:136
static void writeToErrorList(const ErrorMessage &errmsg)
Write given error to stdout in xml format.
Definition: check.cpp:58
ErrorPath getErrorPath(const Token *errtok, const ValueFlow::Value *value, std::string bug) const
Definition: check.cpp:111
ErrorLogger *const mErrorLogger
Definition: check.h:137
const Tokenizer *const mTokenizer
Definition: check.h:135
static std::string getMessageId(const ValueFlow::Value &value, const char id[])
Definition: check.cpp:102
void logChecker(const char id[])
log checker
Definition: check.cpp:129
const std::string & name() const
class name, used to generate documentation
Definition: check.h:88
bool wrongData(const Token *tok, const char *str)
Use WRONG_DATA in checkers when you check for wrong data.
Definition: check.cpp:82
virtual void reportErr(const ErrorMessage &msg)=0
Information about found errors and warnings is directed here.
Wrapper for error messages, provided by reportErr()
Definition: errorlogger.h:48
std::string toXML() const
Format the error message in XML format.
bool xml
write XML results (–xml)
Definition: settings.h:399
std::string templateLocation
The output format in which the error locations are printed in text mode, e.g.
Definition: settings.h:375
bool daca
Are we running from DACA script?
Definition: settings.h:172
bool verbose
Is –verbose given?
Definition: settings.h:396
The token list that the TokenList generates is a linked-list of this class.
Definition: token.h:150
std::string expressionString() const
Definition: token.cpp:1681
TokenList list
Token list: stores all tokens.
Definition: tokenize.h:607
ErrorPath errorPath
Definition: vfvalue.h:282
const Token * condition
Condition that this value depends on.
Definition: vfvalue.h:280
bool safe
value relies on safe checking
Definition: vfvalue.h:290
Severity
enum class for severity.
Definition: errortypes.h:63
Certainty
Definition: errortypes.h:54
std::list< ErrorPathItem > ErrorPath
Definition: errortypes.h:130
@ debug
Debug message.
@ internal
Internal message.