/src/cppcheck/oss-fuzz/build/check.cpp
Line | Count | Source (jump to first uncovered line) |
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 | 50 | : mName(aname) |
39 | 50 | { |
40 | 50 | { |
41 | 600 | const auto it = std::find_if(instances().begin(), instances().end(), [&](const Check *i) { |
42 | 600 | return i->name() == aname; |
43 | 600 | }); |
44 | 50 | if (it != instances().end()) |
45 | 0 | throw std::runtime_error("'" + aname + "' instance already exists"); |
46 | 50 | } |
47 | | |
48 | | // make sure the instances are sorted |
49 | 590 | const auto it = std::find_if(instances().begin(), instances().end(), [&](const Check* i) { |
50 | 590 | return i->name() > aname; |
51 | 590 | }); |
52 | 50 | if (it == instances().end()) |
53 | 32 | instances().push_back(this); |
54 | 18 | else |
55 | 18 | instances().insert(it, this); |
56 | 50 | } |
57 | | |
58 | | void Check::writeToErrorList(const ErrorMessage &errmsg) |
59 | 0 | { |
60 | 0 | std::cout << errmsg.toXML() << std::endl; |
61 | 0 | } |
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 | 133k | { |
66 | | // TODO: report debug warning when error is for a disabled severity |
67 | 133k | const ErrorMessage errmsg(callstack, mTokenizer ? &mTokenizer->list : nullptr, severity, id, msg, cwe, certainty); |
68 | 133k | if (mErrorLogger) |
69 | 133k | mErrorLogger->reportErr(errmsg); |
70 | 0 | else |
71 | 0 | writeToErrorList(errmsg); |
72 | 133k | } |
73 | | |
74 | | void Check::reportError(const ErrorPath &errorPath, Severity severity, const char id[], const std::string &msg, const CWE &cwe, Certainty certainty) |
75 | 361 | { |
76 | | // TODO: report debug warning when error is for a disabled severity |
77 | 361 | const ErrorMessage errmsg(errorPath, mTokenizer ? &mTokenizer->list : nullptr, severity, id, msg, cwe, certainty); |
78 | 361 | if (mErrorLogger) |
79 | 361 | mErrorLogger->reportErr(errmsg); |
80 | 0 | else |
81 | 0 | writeToErrorList(errmsg); |
82 | 361 | } |
83 | | |
84 | | bool Check::wrongData(const Token *tok, const char *str) |
85 | 0 | { |
86 | 0 | if (mSettings->daca) |
87 | 0 | reportError(tok, Severity::debug, "DacaWrongData", "Wrong data detected by condition " + std::string(str)); |
88 | 0 | return true; |
89 | 0 | } |
90 | | |
91 | | std::list<Check *> &Check::instances() |
92 | 1.87k | { |
93 | | #ifdef __SVR4 |
94 | | // Under Solaris, destructors are called in wrong order which causes a segmentation fault. |
95 | | // This fix ensures pointer remains valid and reachable until program terminates. |
96 | | static std::list<Check *> *_instances= new std::list<Check *>; |
97 | | return *_instances; |
98 | | #else |
99 | 1.87k | static std::list<Check *> _instances; |
100 | 1.87k | return _instances; |
101 | 1.87k | #endif |
102 | 1.87k | } |
103 | | |
104 | | std::string Check::getMessageId(const ValueFlow::Value &value, const char id[]) |
105 | 0 | { |
106 | 0 | if (value.condition != nullptr) |
107 | 0 | return id + std::string("Cond"); |
108 | 0 | if (value.safe) |
109 | 0 | return std::string("safe") + (char)std::toupper(id[0]) + (id + 1); |
110 | 0 | return id; |
111 | 0 | } |
112 | | |
113 | | ErrorPath Check::getErrorPath(const Token* errtok, const ValueFlow::Value* value, std::string bug) const |
114 | 41 | { |
115 | 41 | ErrorPath errorPath; |
116 | 41 | if (!value) { |
117 | 0 | errorPath.emplace_back(errtok, std::move(bug)); |
118 | 41 | } else if (mSettings->verbose || mSettings->xml || !mSettings->templateLocation.empty()) { |
119 | 0 | errorPath = value->errorPath; |
120 | 0 | errorPath.emplace_back(errtok, std::move(bug)); |
121 | 41 | } else { |
122 | 41 | if (value->condition) |
123 | 0 | errorPath.emplace_back(value->condition, "condition '" + value->condition->expressionString() + "'"); |
124 | | //else if (!value->isKnown() || value->defaultArg) |
125 | | // errorPath = value->callstack; |
126 | 41 | errorPath.emplace_back(errtok, std::move(bug)); |
127 | 41 | } |
128 | 41 | return errorPath; |
129 | 41 | } |
130 | | |
131 | | void Check::logChecker(const char id[]) |
132 | 133k | { |
133 | 133k | reportError(nullptr, Severity::internal, "logChecker", id); |
134 | 133k | } |
135 | | |