/src/cppcheck/lib/checkio.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- C++ -*- |
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 | | |
27 | | #include <cstdint> |
28 | | #include <ostream> |
29 | | #include <string> |
30 | | |
31 | | class Function; |
32 | | class Settings; |
33 | | class Token; |
34 | | class Variable; |
35 | | class ErrorLogger; |
36 | | class Tokenizer; |
37 | | enum class Severity : std::uint8_t; |
38 | | |
39 | | /// @addtogroup Checks |
40 | | /// @{ |
41 | | |
42 | | /** @brief %Check input output operations. */ |
43 | | class CPPCHECKLIB CheckIO : public Check { |
44 | | friend class TestIO; |
45 | | |
46 | | public: |
47 | | /** @brief This constructor is used when registering CheckIO */ |
48 | 2 | CheckIO() : Check(myName()) {} |
49 | | |
50 | | private: |
51 | | /** @brief This constructor is used when running checks. */ |
52 | | CheckIO(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) |
53 | 763 | : Check(myName(), tokenizer, settings, errorLogger) {} |
54 | | |
55 | | /** @brief Run checks on the normal token list */ |
56 | | void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override; |
57 | | |
58 | | /** @brief %Check for missusage of std::cout */ |
59 | | void checkCoutCerrMisusage(); |
60 | | |
61 | | /** @brief %Check usage of files*/ |
62 | | void checkFileUsage(); |
63 | | |
64 | | /** @brief scanf can crash if width specifiers are not used */ |
65 | | void invalidScanf(); |
66 | | |
67 | | /** @brief %Checks type and number of arguments given to functions like printf or scanf*/ |
68 | | void checkWrongPrintfScanfArguments(); |
69 | | |
70 | | class ArgumentInfo { |
71 | | public: |
72 | | ArgumentInfo(const Token *arg, const Settings &settings, bool _isCPP); |
73 | | ~ArgumentInfo(); |
74 | | |
75 | | ArgumentInfo(const ArgumentInfo &) = delete; |
76 | | ArgumentInfo& operator= (const ArgumentInfo &) = delete; |
77 | | |
78 | | bool isArrayOrPointer() const; |
79 | | bool isComplexType() const; |
80 | | bool isKnownType() const; |
81 | | bool isStdVectorOrString(); |
82 | | bool isStdContainer(const Token *tok); |
83 | | bool isLibraryType(const Settings &settings) const; |
84 | | |
85 | | const Variable* variableInfo{}; |
86 | | const Token* typeToken{}; |
87 | | const Function* functionInfo{}; |
88 | | Token* tempToken{}; |
89 | | bool element{}; |
90 | | bool _template{}; |
91 | | bool address{}; |
92 | | bool isCPP{}; |
93 | | }; |
94 | | |
95 | | void checkFormatString(const Token * tok, |
96 | | const Token * formatStringTok, |
97 | | const Token * argListTok, |
98 | | bool scan, |
99 | | bool scanf_s); |
100 | | |
101 | | // Reporting errors.. |
102 | | void coutCerrMisusageError(const Token* tok, const std::string& streamName); |
103 | | void fflushOnInputStreamError(const Token *tok, const std::string &varname); |
104 | | void ioWithoutPositioningError(const Token *tok); |
105 | | void readWriteOnlyFileError(const Token *tok); |
106 | | void writeReadOnlyFileError(const Token *tok); |
107 | | void useClosedFileError(const Token *tok); |
108 | | void seekOnAppendedFileError(const Token *tok); |
109 | | void incompatibleFileOpenError(const Token *tok, const std::string &filename); |
110 | | void invalidScanfError(const Token *tok); |
111 | | void wrongPrintfScanfArgumentsError(const Token* tok, |
112 | | const std::string &functionName, |
113 | | nonneg int numFormat, |
114 | | nonneg int numFunction); |
115 | | void wrongPrintfScanfPosixParameterPositionError(const Token* tok, const std::string& functionName, |
116 | | nonneg int index, nonneg int numFunction); |
117 | | void invalidScanfArgTypeError_s(const Token* tok, nonneg int numFormat, const std::string& specifier, const ArgumentInfo* argInfo); |
118 | | void invalidScanfArgTypeError_int(const Token* tok, nonneg int numFormat, const std::string& specifier, const ArgumentInfo* argInfo, bool isUnsigned); |
119 | | void invalidScanfArgTypeError_float(const Token* tok, nonneg int numFormat, const std::string& specifier, const ArgumentInfo* argInfo); |
120 | | void invalidPrintfArgTypeError_s(const Token* tok, nonneg int numFormat, const ArgumentInfo* argInfo); |
121 | | void invalidPrintfArgTypeError_n(const Token* tok, nonneg int numFormat, const ArgumentInfo* argInfo); |
122 | | void invalidPrintfArgTypeError_p(const Token* tok, nonneg int numFormat, const ArgumentInfo* argInfo); |
123 | | void invalidPrintfArgTypeError_uint(const Token* tok, nonneg int numFormat, const std::string& specifier, const ArgumentInfo* argInfo); |
124 | | void invalidPrintfArgTypeError_sint(const Token* tok, nonneg int numFormat, const std::string& specifier, const ArgumentInfo* argInfo); |
125 | | void invalidPrintfArgTypeError_float(const Token* tok, nonneg int numFormat, const std::string& specifier, const ArgumentInfo* argInfo); |
126 | | void invalidLengthModifierError(const Token* tok, nonneg int numFormat, const std::string& modifier); |
127 | | void invalidScanfFormatWidthError(const Token* tok, nonneg int numFormat, int width, const Variable *var, const std::string& specifier); |
128 | | static void argumentType(std::ostream & os, const ArgumentInfo * argInfo); |
129 | | static Severity getSeverity(const ArgumentInfo *argInfo); |
130 | | |
131 | | void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override; |
132 | | |
133 | 765 | static std::string myName() { |
134 | 765 | return "IO using format string"; |
135 | 765 | } |
136 | | |
137 | 0 | std::string classInfo() const override { |
138 | 0 | return "Check format string input/output operations.\n" |
139 | 0 | "- Bad usage of the function 'sprintf' (overlapping data)\n" |
140 | 0 | "- Missing or wrong width specifiers in 'scanf' format string\n" |
141 | 0 | "- Use a file that has been closed\n" |
142 | 0 | "- File input/output without positioning results in undefined behaviour\n" |
143 | 0 | "- Read to a file that has only been opened for writing (or vice versa)\n" |
144 | 0 | "- Repositioning operation on a file opened in append mode\n" |
145 | 0 | "- The same file can't be open for read and write at the same time on different streams\n" |
146 | 0 | "- Using fflush() on an input stream\n" |
147 | 0 | "- Invalid usage of output stream. For example: 'std::cout << std::cout;'\n" |
148 | 0 | "- Wrong number of arguments given to 'printf' or 'scanf;'\n"; |
149 | 0 | } |
150 | | }; |
151 | | /// @} |
152 | | //--------------------------------------------------------------------------- |
153 | | #endif // checkioH |