Cppcheck
exprengine.h
Go to the documentation of this file.
1 /*
2  * Cppcheck - A tool for static C/C++ code analysis
3  * Copyright (C) 2007-2022 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 #ifndef exprengineH
21 #define exprengineH
22 //---------------------------------------------------------------------------
23 
24 #include "config.h"
25 #include "errortypes.h"
26 
27 #include <algorithm>
28 #include <functional>
29 #include <iosfwd>
30 #include <map>
31 #include <memory>
32 #include <string>
33 #include <vector>
34 #include <utility>
35 
36 class ErrorLogger;
37 class Tokenizer;
38 class Scope;
39 class Settings;
40 class Token;
41 class Variable;
42 
43 #if defined(__GNUC__) && defined (__SIZEOF_INT128__)
44 typedef __int128_t int128_t;
45 #else
46 typedef long long int128_t;
47 #ifdef _MSC_VER
48 #pragma message(__FILE__ "(" _CRT_STRINGIZE(__LINE__) ")" ": warning: TODO No 128-bit integer type is available => Limited analysis of large integers...")
49 #else
50 #warning TODO No 128-bit integer type is available => Limited analysis of large integers
51 #endif
52 #endif
53 
54 namespace ExprEngine {
55  std::string str(int128_t);
56 
57  // TODO we need to handle floats, containers, pointers, aliases and structs and stuff
58  enum class ValueType {
60  IntRange,
61  FloatRange,
63  ArrayValue,
71  };
72 
73  class Value;
74  typedef std::shared_ptr<Value> ValuePtr;
75 
76  class DataBase {
77  public:
78  explicit DataBase(const std::string &currentFunction, const Settings *settings)
80  , settings(settings) {}
81  virtual std::string getNewSymbolName() = 0;
82  const std::string currentFunction;
83  const Settings * const settings;
84  virtual bool isC() const = 0;
85  virtual bool isCPP() const = 0;
86  virtual void reportError(const Token *tok,
87  Severity::SeverityType severity,
88  const char id[],
89  const std::string &text,
90  CWE cwe,
91  bool inconclusive,
92  bool incomplete=false,
93  const std::string &functionName = std::string()) = 0;
95  };
96 
97  class Value {
98  public:
99  Value(const std::string &name, const ValueType type) : name(name), type(type) {}
100  virtual ~Value() {}
101  virtual std::string getRange() const {
102  return name;
103  }
104  virtual std::string getSymbolicExpression() const {
105  return name;
106  }
107  virtual bool isEqual(const DataBase *dataBase, int value) const {
108  (void)dataBase;
109  (void)value;
110  return false;
111  }
112  virtual bool isGreaterThan(const DataBase *dataBase, int value) const {
113  (void)dataBase;
114  (void)value;
115  return false;
116  }
117  virtual bool isLessThan(const DataBase *dataBase, int value) const {
118  (void)dataBase;
119  (void)value;
120  return false;
121  }
122  virtual bool isUninit(const DataBase *dataBase) const {
123  (void)dataBase;
124  return false;
125  }
126 
127  const std::string name;
129  };
130 
131  class UninitValue : public Value {
132  public:
134  bool isEqual(const DataBase *dataBase, int value) const override {
135  (void)dataBase;
136  (void)value;
137  return true;
138  }
139  bool isUninit(const DataBase *dataBase) const override;
140  };
141 
142  class IntRange : public Value {
143  public:
146  , minValue(minValue)
147  , maxValue(maxValue)
148  , loopScope(nullptr) {}
149  std::string getRange() const override {
150  if (minValue == maxValue)
151  return str(minValue);
152  return str(minValue) + ":" + str(maxValue);
153  }
154  bool isEqual(const DataBase *dataBase, int value) const override;
155  bool isGreaterThan(const DataBase *dataBase, int value) const override;
156  bool isLessThan(const DataBase *dataBase, int value) const override;
157 
160  const Scope *loopScope;
161  };
162 
163  class FloatRange : public Value {
164  public:
165  FloatRange(const std::string &name, long double minValue, long double maxValue)
167  , minValue(minValue)
168  , maxValue(maxValue) {}
169 
170  std::string getRange() const override {
171  return std::to_string(minValue) + ":" + std::to_string(maxValue);
172  }
173 
174  bool isEqual(const DataBase *dataBase, int value) const override;
175  bool isGreaterThan(const DataBase *dataBase, int value) const override;
176  bool isLessThan(const DataBase *dataBase, int value) const override;
177 
178  long double minValue;
179  long double maxValue;
180  };
181 
182  class ConditionalValue : public Value {
183  public:
184  typedef std::vector<std::pair<ValuePtr,ValuePtr>> Vector;
185 
187 
188  std::string getSymbolicExpression() const override;
189 
191  };
192 
193  // Array or pointer
194  class ArrayValue : public Value {
195  public:
196  enum { MAXSIZE = 0x7fffffff };
197 
198  ArrayValue(const std::string &name, ValuePtr size, ValuePtr value, bool pointer, bool nullPointer, bool uninitPointer);
199  ArrayValue(DataBase *data, const Variable *var);
200  ArrayValue(const std::string &name, const ArrayValue &arrayValue);
201 
202  std::string getRange() const override;
203  std::string getSymbolicExpression() const override;
204 
205  void assign(ValuePtr index, ValuePtr value);
206  void clear();
208 
209  bool pointer;
212 
213  struct IndexAndValue {
216  };
217  std::vector<IndexAndValue> data;
218  std::vector<ValuePtr> size;
219  };
220 
221  class StringLiteralValue : public Value {
222  public:
223  StringLiteralValue(const std::string &name, const std::string &s) : Value(name, ValueType::StringLiteralValue), string(s) {}
224 
225  std::string getRange() const override {
226  return "\"" + string + "\"";
227  }
228 
229  int size() const {
230  return string.size();
231  }
232  const std::string string;
233  };
234 
235  class StructValue : public Value {
236  public:
237  explicit StructValue(const std::string &name) : Value(name, ValueType::StructValue) {}
238 
239  std::string getSymbolicExpression() const override;
240 
241  std::string getRange() const override {
242  return getSymbolicExpression();
243  }
244 
245  ValuePtr getValueOfMember(const std::string &n) const {
246  auto it = member.find(n);
247  return (it == member.end()) ? ValuePtr() : it->second;
248  }
249 
250  std::string getUninitStructMember(const DataBase *dataBase) const {
251  for (auto memberNameValue: member) {
252  if (memberNameValue.second && memberNameValue.second->isUninit(dataBase))
253  return memberNameValue.first;
254  }
255  return std::string();
256  }
257 
258  std::map<std::string, ValuePtr> member;
259  };
260 
261  class AddressOfValue : public Value {
262  public:
263  AddressOfValue(const std::string &name, int varId)
265  , varId(varId)
266  {}
267 
268  std::string getRange() const override {
269  return "&@" + std::to_string(varId);
270  }
271 
272  int varId;
273  };
274 
275  class BinOpResult : public Value {
276  public:
277  BinOpResult(const std::string &binop, ValuePtr op1, ValuePtr op2)
279  , binop(binop)
280  , op1(op1)
281  , op2(op2) {}
282 
283  bool isEqual(const DataBase *dataBase, int value) const override;
284  bool isGreaterThan(const DataBase *dataBase, int value) const override;
285  virtual bool isLessThan(const DataBase *dataBase, int value) const override;
286  bool isTrue(const DataBase *dataBase) const;
287 
288  std::string getExpr(DataBase *dataBase) const;
289 
290  std::string binop;
293  private:
294  static std::string getName(const std::string& binop, ValuePtr op1, ValuePtr op2) {
295  std::string name1 = op1 ? op1->name : std::string("null");
296  std::string name2 = op2 ? op2->name : std::string("null");
297  return "(" + name1 + ")" + binop + "(" + name2 + ")";
298  }
299  };
300 
301  class IntegerTruncation : public Value {
302  public:
303  IntegerTruncation(const std::string &name, ValuePtr inputValue, int bits, char sign)
306  , bits(bits)
307  , sign(sign) {}
308 
309  std::string getSymbolicExpression() const override;
310 
312  int bits;
313  char sign;
314  };
315 
317  public:
318  explicit FunctionCallArgumentValues(const std::vector<ExprEngine::ValuePtr> &argValues)
321  {}
322 
323  const std::vector<ExprEngine::ValuePtr> argValues;
324  };
325 
326  class BailoutValue : public Value {
327  public:
329  bool isEqual(const DataBase * /*dataBase*/, int /*value*/) const override {
330  return true;
331  }
332  bool isUninit(const DataBase *dataBase) const override {
333  (void)dataBase;
334  return true;
335  }
336  };
337 
338  typedef std::function<void (const Token *, const ExprEngine::Value &, ExprEngine::DataBase *)> Callback;
339 
340  /** Execute all functions */
341  void CPPCHECKLIB executeAllFunctions(ErrorLogger *errorLogger, const Tokenizer *tokenizer, const Settings *settings, const std::vector<Callback> &callbacks, std::ostream &report);
342  void executeFunction(const Scope *functionScope, ErrorLogger *errorLogger, const Tokenizer *tokenizer, const Settings *settings, const std::vector<Callback> &callbacks, std::ostream &report);
343 
344  void runChecks(ErrorLogger *errorLogger, const Tokenizer *tokenizer, const Settings *settings);
345 
346  void dump(ExprEngine::ValuePtr val);
347 }
348 #endif // exprengineH
This is an interface, which the class responsible of error logging should implement.
Definition: errorlogger.h:238
AddressOfValue(const std::string &name, int varId)
Definition: exprengine.h:263
std::string getRange() const override
Definition: exprengine.h:268
std::string getSymbolicExpression() const override
std::vector< IndexAndValue > data
Definition: exprengine.h:217
std::vector< ValuePtr > size
Definition: exprengine.h:218
ArrayValue(const std::string &name, ValuePtr size, ValuePtr value, bool pointer, bool nullPointer, bool uninitPointer)
Definition: exprengine.cpp:890
void assign(ValuePtr index, ValuePtr value)
Definition: exprengine.cpp:945
ConditionalValue::Vector read(ValuePtr index) const
Definition: exprengine.cpp:992
std::string getRange() const override
Definition: exprengine.cpp:935
bool isUninit(const DataBase *dataBase) const override
Definition: exprengine.h:332
bool isEqual(const DataBase *, int) const override
Definition: exprengine.h:329
bool isTrue(const DataBase *dataBase) const
static std::string getName(const std::string &binop, ValuePtr op1, ValuePtr op2)
Definition: exprengine.h:294
BinOpResult(const std::string &binop, ValuePtr op1, ValuePtr op2)
Definition: exprengine.h:277
virtual bool isLessThan(const DataBase *dataBase, int value) const override
bool isGreaterThan(const DataBase *dataBase, int value) const override
bool isEqual(const DataBase *dataBase, int value) const override
std::string getExpr(DataBase *dataBase) const
std::string getSymbolicExpression() const override
std::vector< std::pair< ValuePtr, ValuePtr > > Vector
Definition: exprengine.h:184
ConditionalValue(const std::string &name, const Vector &values)
Definition: exprengine.h:186
virtual void reportError(const Token *tok, Severity::SeverityType severity, const char id[], const std::string &text, CWE cwe, bool inconclusive, bool incomplete=false, const std::string &functionName=std::string())=0
ErrorPath errorPath
Definition: exprengine.h:94
virtual bool isC() const =0
virtual bool isCPP() const =0
DataBase(const std::string &currentFunction, const Settings *settings)
Definition: exprengine.h:78
const std::string currentFunction
Definition: exprengine.h:82
virtual std::string getNewSymbolName()=0
const Settings *const settings
Definition: exprengine.h:83
bool isEqual(const DataBase *dataBase, int value) const override
long double minValue
Definition: exprengine.h:178
std::string getRange() const override
Definition: exprengine.h:170
bool isGreaterThan(const DataBase *dataBase, int value) const override
bool isLessThan(const DataBase *dataBase, int value) const override
FloatRange(const std::string &name, long double minValue, long double maxValue)
Definition: exprengine.h:165
long double maxValue
Definition: exprengine.h:179
FunctionCallArgumentValues(const std::vector< ExprEngine::ValuePtr > &argValues)
Definition: exprengine.h:318
const std::vector< ExprEngine::ValuePtr > argValues
Definition: exprengine.h:323
const Scope * loopScope
Definition: exprengine.h:160
bool isLessThan(const DataBase *dataBase, int value) const override
IntRange(const std::string &name, int128_t minValue, int128_t maxValue)
Definition: exprengine.h:144
bool isGreaterThan(const DataBase *dataBase, int value) const override
bool isEqual(const DataBase *dataBase, int value) const override
std::string getRange() const override
Definition: exprengine.h:149
IntegerTruncation(const std::string &name, ValuePtr inputValue, int bits, char sign)
Definition: exprengine.h:303
std::string getSymbolicExpression() const override
ExprEngine::ValuePtr inputValue
Definition: exprengine.h:311
const std::string string
Definition: exprengine.h:232
std::string getRange() const override
Definition: exprengine.h:225
StringLiteralValue(const std::string &name, const std::string &s)
Definition: exprengine.h:223
std::map< std::string, ValuePtr > member
Definition: exprengine.h:258
std::string getUninitStructMember(const DataBase *dataBase) const
Definition: exprengine.h:250
std::string getSymbolicExpression() const override
ValuePtr getValueOfMember(const std::string &n) const
Definition: exprengine.h:245
StructValue(const std::string &name)
Definition: exprengine.h:237
std::string getRange() const override
Definition: exprengine.h:241
bool isUninit(const DataBase *dataBase) const override
bool isEqual(const DataBase *dataBase, int value) const override
Definition: exprengine.h:134
ValueType type
Definition: exprengine.h:128
virtual std::string getRange() const
Definition: exprengine.h:101
virtual ~Value()
Definition: exprengine.h:100
virtual bool isGreaterThan(const DataBase *dataBase, int value) const
Definition: exprengine.h:112
const std::string name
Definition: exprengine.h:127
Value(const std::string &name, const ValueType type)
Definition: exprengine.h:99
virtual std::string getSymbolicExpression() const
Definition: exprengine.h:104
virtual bool isEqual(const DataBase *dataBase, int value) const
Definition: exprengine.h:107
virtual bool isUninit(const DataBase *dataBase) const
Definition: exprengine.h:122
virtual bool isLessThan(const DataBase *dataBase, int value) const
Definition: exprengine.h:117
This is just a container for general settings so that we don't need to pass individual values to func...
Definition: settings.h:91
SeverityType
Message severities.
Definition: errortypes.h:64
The token list that the TokenList generates is a linked-list of this class.
Definition: token.h:172
The main purpose is to tokenize the source code.
Definition: tokenize.h:52
Value type.
Information about a member variable.
#define CPPCHECKLIB
Definition: config.h:31
long long int128_t
Definition: exprengine.h:41
std::list< ErrorPathItem > ErrorPath
Definition: errortypes.h:126
void executeFunction(const Scope *functionScope, ErrorLogger *errorLogger, const Tokenizer *tokenizer, const Settings *settings, const std::vector< Callback > &callbacks, std::ostream &report)
void runChecks(ErrorLogger *errorLogger, const Tokenizer *tokenizer, const Settings *settings)
std::shared_ptr< Value > ValuePtr
Definition: exprengine.h:73
void CPPCHECKLIB executeAllFunctions(ErrorLogger *errorLogger, const Tokenizer *tokenizer, const Settings *settings, const std::vector< Callback > &callbacks, std::ostream &report)
Execute all functions.
void dump(ExprEngine::ValuePtr val)
std::function< void(const Token *, const ExprEngine::Value &, ExprEngine::DataBase *)> Callback
Definition: exprengine.h:338
std::string str(int128_t)
Definition: exprengine.cpp:245