Cppcheck
checkio.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 #ifndef checkioH
21 #define checkioH
22 //---------------------------------------------------------------------------
23 
24 #include "check.h"
25 #include "config.h"
26 #include "tokenize.h"
27 
28 #include <ostream>
29 #include <string>
30 
31 class Function;
32 class Settings;
33 class Token;
34 class Variable;
35 class ErrorLogger;
36 enum class Severity;
37 
38 /// @addtogroup Checks
39 /// @{
40 
41 /** @brief %Check input output operations. */
42 class CPPCHECKLIB CheckIO : public Check {
43  friend class TestIO;
44 
45 public:
46  /** @brief This constructor is used when registering CheckIO */
47  CheckIO() : Check(myName()) {}
48 
49 private:
50  /** @brief This constructor is used when running checks. */
51  CheckIO(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
52  : Check(myName(), tokenizer, settings, errorLogger) {}
53 
54  /** @brief Run checks on the normal token list */
55  void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override {
56  CheckIO checkIO(&tokenizer, &tokenizer.getSettings(), errorLogger);
57 
59  checkIO.checkCoutCerrMisusage();
60  checkIO.checkFileUsage();
61  checkIO.invalidScanf();
62  }
63 
64  /** @brief %Check for missusage of std::cout */
65  void checkCoutCerrMisusage();
66 
67  /** @brief %Check usage of files*/
68  void checkFileUsage();
69 
70  /** @brief scanf can crash if width specifiers are not used */
71  void invalidScanf();
72 
73  /** @brief %Checks type and number of arguments given to functions like printf or scanf*/
74  void checkWrongPrintfScanfArguments();
75 
76  class ArgumentInfo {
77  public:
78  ArgumentInfo(const Token *arg, const Settings &settings, bool _isCPP);
79  ~ArgumentInfo();
80 
81  ArgumentInfo(const ArgumentInfo &) = delete;
82  ArgumentInfo& operator= (const ArgumentInfo &) = delete;
83 
84  bool isArrayOrPointer() const;
85  bool isComplexType() const;
86  bool isKnownType() const;
87  bool isStdVectorOrString();
88  bool isStdContainer(const Token *tok);
89  bool isLibraryType(const Settings &settings) const;
90 
91  const Variable* variableInfo{};
92  const Token* typeToken{};
93  const Function* functionInfo{};
94  Token* tempToken{};
95  bool element{};
96  bool _template{};
97  bool address{};
98  bool isCPP{};
99  };
100 
101  void checkFormatString(const Token * const tok,
102  const Token * const formatStringTok,
103  const Token * argListTok,
104  const bool scan,
105  const bool scanf_s);
106 
107  // Reporting errors..
108  void coutCerrMisusageError(const Token* tok, const std::string& streamName);
109  void fflushOnInputStreamError(const Token *tok, const std::string &varname);
110  void ioWithoutPositioningError(const Token *tok);
111  void readWriteOnlyFileError(const Token *tok);
112  void writeReadOnlyFileError(const Token *tok);
113  void useClosedFileError(const Token *tok);
114  void seekOnAppendedFileError(const Token *tok);
115  void incompatibleFileOpenError(const Token *tok, const std::string &filename);
116  void invalidScanfError(const Token *tok);
117  void wrongPrintfScanfArgumentsError(const Token* tok,
118  const std::string &functionName,
119  nonneg int numFormat,
120  nonneg int numFunction);
121  void wrongPrintfScanfPosixParameterPositionError(const Token* tok, const std::string& functionName,
122  nonneg int index, nonneg int numFunction);
123  void invalidScanfArgTypeError_s(const Token* tok, nonneg int numFormat, const std::string& specifier, const ArgumentInfo* argInfo);
124  void invalidScanfArgTypeError_int(const Token* tok, nonneg int numFormat, const std::string& specifier, const ArgumentInfo* argInfo, bool isUnsigned);
125  void invalidScanfArgTypeError_float(const Token* tok, nonneg int numFormat, const std::string& specifier, const ArgumentInfo* argInfo);
126  void invalidPrintfArgTypeError_s(const Token* tok, nonneg int numFormat, const ArgumentInfo* argInfo);
127  void invalidPrintfArgTypeError_n(const Token* tok, nonneg int numFormat, const ArgumentInfo* argInfo);
128  void invalidPrintfArgTypeError_p(const Token* tok, nonneg int numFormat, const ArgumentInfo* argInfo);
129  void invalidPrintfArgTypeError_uint(const Token* tok, nonneg int numFormat, const std::string& specifier, const ArgumentInfo* argInfo);
130  void invalidPrintfArgTypeError_sint(const Token* tok, nonneg int numFormat, const std::string& specifier, const ArgumentInfo* argInfo);
131  void invalidPrintfArgTypeError_float(const Token* tok, nonneg int numFormat, const std::string& specifier, const ArgumentInfo* argInfo);
132  void invalidLengthModifierError(const Token* tok, nonneg int numFormat, const std::string& modifier);
133  void invalidScanfFormatWidthError(const Token* tok, nonneg int numFormat, int width, const Variable *var, const std::string& specifier);
134  static void argumentType(std::ostream & os, const ArgumentInfo * argInfo);
135  static Severity getSeverity(const ArgumentInfo *argInfo);
136 
137  void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override {
138  CheckIO c(nullptr, settings, errorLogger);
139  c.coutCerrMisusageError(nullptr, "cout");
140  c.fflushOnInputStreamError(nullptr, "stdin");
141  c.ioWithoutPositioningError(nullptr);
142  c.readWriteOnlyFileError(nullptr);
143  c.writeReadOnlyFileError(nullptr);
144  c.useClosedFileError(nullptr);
145  c.seekOnAppendedFileError(nullptr);
146  c.incompatibleFileOpenError(nullptr, "tmp");
147  c.invalidScanfError(nullptr);
148  c.wrongPrintfScanfArgumentsError(nullptr, "printf",3,2);
149  c.invalidScanfArgTypeError_s(nullptr, 1, "s", nullptr);
150  c.invalidScanfArgTypeError_int(nullptr, 1, "d", nullptr, false);
151  c.invalidScanfArgTypeError_float(nullptr, 1, "f", nullptr);
152  c.invalidPrintfArgTypeError_s(nullptr, 1, nullptr);
153  c.invalidPrintfArgTypeError_n(nullptr, 1, nullptr);
154  c.invalidPrintfArgTypeError_p(nullptr, 1, nullptr);
155  c.invalidPrintfArgTypeError_uint(nullptr, 1, "u", nullptr);
156  c.invalidPrintfArgTypeError_sint(nullptr, 1, "i", nullptr);
157  c.invalidPrintfArgTypeError_float(nullptr, 1, "f", nullptr);
158  c.invalidLengthModifierError(nullptr, 1, "I");
159  c.invalidScanfFormatWidthError(nullptr, 10, 5, nullptr, "s");
160  c.invalidScanfFormatWidthError(nullptr, 99, -1, nullptr, "s");
161  c.wrongPrintfScanfPosixParameterPositionError(nullptr, "printf", 2, 1);
162  }
163 
164  static std::string myName() {
165  return "IO using format string";
166  }
167 
168  std::string classInfo() const override {
169  return "Check format string input/output operations.\n"
170  "- Bad usage of the function 'sprintf' (overlapping data)\n"
171  "- Missing or wrong width specifiers in 'scanf' format string\n"
172  "- Use a file that has been closed\n"
173  "- File input/output without positioning results in undefined behaviour\n"
174  "- Read to a file that has only been opened for writing (or vice versa)\n"
175  "- Repositioning operation on a file opened in append mode\n"
176  "- The same file can't be open for read and write at the same time on different streams\n"
177  "- Using fflush() on an input stream\n"
178  "- Invalid usage of output stream. For example: 'std::cout << std::cout;'\n"
179  "- Wrong number of arguments given to 'printf' or 'scanf;'\n";
180  }
181 };
182 /// @}
183 //---------------------------------------------------------------------------
184 #endif // checkioH
ArgumentInfo(const ArgumentInfo &)=delete
Check input output operations.
Definition: checkio.h:42
void invalidPrintfArgTypeError_uint(const Token *tok, nonneg int numFormat, const std::string &specifier, const ArgumentInfo *argInfo)
Definition: checkio.cpp:1898
void invalidScanf()
scanf can crash if width specifiers are not used
Definition: checkio.cpp:412
void invalidPrintfArgTypeError_n(const Token *tok, nonneg int numFormat, const ArgumentInfo *argInfo)
Definition: checkio.cpp:1837
void seekOnAppendedFileError(const Token *tok)
Definition: checkio.cpp:396
void incompatibleFileOpenError(const Token *tok, const std::string &filename)
Definition: checkio.cpp:402
void invalidPrintfArgTypeError_s(const Token *tok, nonneg int numFormat, const ArgumentInfo *argInfo)
Definition: checkio.cpp:1826
void writeReadOnlyFileError(const Token *tok)
Definition: checkio.cpp:384
void readWriteOnlyFileError(const Token *tok)
Definition: checkio.cpp:378
static std::string myName()
Definition: checkio.h:164
CheckIO(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
This constructor is used when running checks.
Definition: checkio.h:51
void invalidLengthModifierError(const Token *tok, nonneg int numFormat, const std::string &modifier)
Definition: checkio.cpp:1995
void checkCoutCerrMisusage()
Check for missusage of std::cout
Definition: checkio.cpp:66
void fflushOnInputStreamError(const Token *tok, const std::string &varname)
Definition: checkio.cpp:366
void invalidScanfArgTypeError_float(const Token *tok, nonneg int numFormat, const std::string &specifier, const ArgumentInfo *argInfo)
Definition: checkio.cpp:1807
void invalidScanfError(const Token *tok)
Definition: checkio.cpp:459
void wrongPrintfScanfPosixParameterPositionError(const Token *tok, const std::string &functionName, nonneg int index, nonneg int numFunction)
Definition: checkio.cpp:1731
void invalidScanfFormatWidthError(const Token *tok, nonneg int numFormat, int width, const Variable *var, const std::string &specifier)
Definition: checkio.cpp:2004
void invalidPrintfArgTypeError_sint(const Token *tok, nonneg int numFormat, const std::string &specifier, const ArgumentInfo *argInfo)
Definition: checkio.cpp:1912
void coutCerrMisusageError(const Token *tok, const std::string &streamName)
Definition: checkio.cpp:88
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override
get error messages
Definition: checkio.h:137
void checkFileUsage()
Check usage of files
Definition: checkio.cpp:127
void checkWrongPrintfScanfArguments()
Checks type and number of arguments given to functions like printf or scanf
Definition: checkio.cpp:531
void invalidScanfArgTypeError_int(const Token *tok, nonneg int numFormat, const std::string &specifier, const ArgumentInfo *argInfo, bool isUnsigned)
Definition: checkio.cpp:1762
void invalidPrintfArgTypeError_p(const Token *tok, nonneg int numFormat, const ArgumentInfo *argInfo)
Definition: checkio.cpp:1848
void ioWithoutPositioningError(const Token *tok)
Definition: checkio.cpp:372
void invalidPrintfArgTypeError_float(const Token *tok, nonneg int numFormat, const std::string &specifier, const ArgumentInfo *argInfo)
Definition: checkio.cpp:1925
void invalidScanfArgTypeError_s(const Token *tok, nonneg int numFormat, const std::string &specifier, const ArgumentInfo *argInfo)
Definition: checkio.cpp:1746
void useClosedFileError(const Token *tok)
Definition: checkio.cpp:390
void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override
Run checks on the normal token list.
Definition: checkio.h:55
void wrongPrintfScanfArgumentsError(const Token *tok, const std::string &functionName, nonneg int numFormat, nonneg int numFunction)
Definition: checkio.cpp:1709
CheckIO()
This constructor is used when registering CheckIO.
Definition: checkio.h:47
std::string classInfo() const override
get information about this class, used to generate documentation
Definition: checkio.h:168
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
Information about a member variable.
#define CPPCHECKLIB
Definition: config.h:35
#define nonneg
Definition: config.h:138
Severity
enum class for severity.
Definition: errortypes.h:63