Cppcheck
checkleakautovar.h
Go to the documentation of this file.
1 /*
2  * Cppcheck - A tool for static C/C++ code analysis
3  * Copyright (C) 2007-2024 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 #ifndef checkleakautovarH
22 #define checkleakautovarH
23 //---------------------------------------------------------------------------
24 
25 #include "check.h"
26 #include "config.h"
27 #include "library.h"
28 #include "tokenize.h"
29 
30 #include <map>
31 #include <set>
32 #include <string>
33 
34 class ErrorLogger;
35 class Settings;
36 class Token;
37 
38 
39 class CPPCHECKLIB VarInfo {
40 public:
41  enum AllocStatus { REALLOC = -3, OWNED = -2, DEALLOC = -1, NOALLOC = 0, ALLOC = 1 };
42  struct AllocInfo {
44  /** Allocation type. If it is a positive value then it corresponds to
45  * a Library allocation id. A negative value is a builtin
46  * checkleakautovar allocation type.
47  */
48  int type;
49  int reallocedFromType = -1;
50  const Token * allocTok;
51  explicit AllocInfo(int type_ = 0, AllocStatus status_ = NOALLOC, const Token* allocTok_ = nullptr) : status(status_), type(type_), allocTok(allocTok_) {}
52 
53  bool managed() const {
54  return status < 0;
55  }
56  };
57  enum Usage { USED, NORET };
58  std::map<int, AllocInfo> alloctype;
59  std::map<int, std::pair<const Token*, Usage>> possibleUsage;
60  std::set<int> conditionalAlloc;
61  std::set<int> referenced;
62 
63  void clear() {
64  alloctype.clear();
65  possibleUsage.clear();
66  conditionalAlloc.clear();
67  referenced.clear();
68  }
69 
70  void erase(nonneg int varid) {
71  alloctype.erase(varid);
72  possibleUsage.erase(varid);
73  conditionalAlloc.erase(varid);
74  referenced.erase(varid);
75  }
76 
77  void swap(VarInfo &other) {
78  alloctype.swap(other.alloctype);
79  possibleUsage.swap(other.possibleUsage);
80  conditionalAlloc.swap(other.conditionalAlloc);
81  referenced.swap(other.referenced);
82  }
83 
84  void reallocToAlloc(nonneg int varid) {
85  const AllocInfo& alloc = alloctype[varid];
86  if (alloc.reallocedFromType >= 0) {
87  const std::map<int, VarInfo::AllocInfo>::iterator it = alloctype.find(alloc.reallocedFromType);
88  if (it != alloctype.end() && it->second.status == REALLOC) {
89  it->second.status = ALLOC;
90  }
91  }
92  }
93 
94  /** set possible usage for all variables */
95  void possibleUsageAll(const std::pair<const Token*, Usage>& functionUsage);
96 
97  void print();
98 };
99 
100 
101 /// @addtogroup Checks
102 /// @{
103 
104 /**
105  * @brief Check for leaks
106  */
107 
109 public:
110  /** This constructor is used when registering the CheckLeakAutoVar */
111  CheckLeakAutoVar() : Check(myName()) {}
112 
113 private:
114  /** This constructor is used when running checks. */
115  CheckLeakAutoVar(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
116  : Check(myName(), tokenizer, settings, errorLogger) {}
117 
118  void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override {
119  CheckLeakAutoVar checkLeakAutoVar(&tokenizer, &tokenizer.getSettings(), errorLogger);
120  checkLeakAutoVar.check();
121  }
122 
123  /** check for leaks in all scopes */
124  void check();
125 
126  /** check for leaks in a function scope */
127  bool checkScope(const Token * const startToken,
128  VarInfo &varInfo,
129  std::set<int> notzero,
130  nonneg int recursiveCount);
131 
132  /** Check token inside expression.
133  * @param tok token inside expression.
134  * @param varInfo Variable info
135  * @return next token to process (if no other checks needed for this token). NULL if other checks could be performed.
136  */
137  const Token * checkTokenInsideExpression(const Token * const tok, VarInfo &varInfo, bool inFuncCall = false);
138 
139  /** parse function call */
140  void functionCall(const Token *tokName, const Token *tokOpeningPar, VarInfo &varInfo, const VarInfo::AllocInfo& allocation, const Library::AllocFunc* af);
141 
142  /** parse changes in allocation status */
143  void changeAllocStatus(VarInfo &varInfo, const VarInfo::AllocInfo& allocation, const Token* tok, const Token* arg);
144 
145  /** update allocation status if reallocation function */
146  void changeAllocStatusIfRealloc(std::map<int, VarInfo::AllocInfo> &alloctype, const Token *fTok, const Token *retTok) const;
147 
148  /** return. either "return" or end of variable scope is seen */
149  void ret(const Token *tok, VarInfo &varInfo, const bool isEndOfScope = false);
150 
151  /** if variable is allocated then there is a leak */
152  void leakIfAllocated(const Token *vartok, const VarInfo &varInfo);
153 
154  void leakError(const Token* tok, const std::string &varname, int type) const;
155  void mismatchError(const Token* deallocTok, const Token* allocTok, const std::string &varname) const;
156  void deallocUseError(const Token *tok, const std::string &varname) const;
157  void deallocReturnError(const Token *tok, const Token *deallocTok, const std::string &varname);
158  void doubleFreeError(const Token *tok, const Token *prevFreeTok, const std::string &varname, int type);
159 
160  /** message: user configuration is needed to complete analysis */
161  void configurationInfo(const Token* tok, const std::pair<const Token*, VarInfo::Usage>& functionUsage);
162 
163  void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override {
164  CheckLeakAutoVar c(nullptr, settings, errorLogger);
165  c.deallocReturnError(nullptr, nullptr, "p");
166  c.configurationInfo(nullptr, { nullptr, VarInfo::USED }); // user configuration is needed to complete analysis
167  c.doubleFreeError(nullptr, nullptr, "varname", 0);
168  }
169 
170  static std::string myName() {
171  return "Leaks (auto variables)";
172  }
173 
174  std::string classInfo() const override {
175  return "Detect when a auto variable is allocated but not deallocated or deallocated twice.\n";
176  }
177 };
178 /// @}
179 //---------------------------------------------------------------------------
180 #endif // checkleakautovarH
Check for leaks.
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override
get error messages
void configurationInfo(const Token *tok, const std::pair< const Token *, VarInfo::Usage > &functionUsage)
message: user configuration is needed to complete analysis
std::string classInfo() const override
get information about this class, used to generate documentation
static std::string myName()
CheckLeakAutoVar(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
This constructor is used when running checks.
void check()
check for leaks in all scopes
CheckLeakAutoVar()
This constructor is used when registering the CheckLeakAutoVar.
void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override
run checks, the token list is not simplified
void doubleFreeError(const Token *tok, const Token *prevFreeTok, const std::string &varname, int type)
void deallocReturnError(const Token *tok, const Token *deallocTok, const std::string &varname)
Interface class that cppcheck uses to communicate with the checks.
Definition: check.h:59
This is an interface, which the class responsible of error logging should implement.
Definition: errorlogger.h:214
This is just a container for general settings so that we don't need to pass individual values to func...
Definition: settings.h:95
The token list that the TokenList generates is a linked-list of this class.
Definition: token.h:150
The main purpose is to tokenize the source code.
Definition: tokenize.h:46
const Settings & getSettings() const
Definition: tokenize.h:615
std::map< int, AllocInfo > alloctype
void erase(nonneg int varid)
std::set< int > conditionalAlloc
void clear()
void swap(VarInfo &other)
std::set< int > referenced
void reallocToAlloc(nonneg int varid)
std::map< int, std::pair< const Token *, Usage > > possibleUsage
#define CPPCHECKLIB
Definition: config.h:35
#define nonneg
Definition: config.h:138
int type
Allocation type.
AllocInfo(int type_=0, AllocStatus status_=NOALLOC, const Token *allocTok_=nullptr)
const Token * allocTok
bool managed() const