Coverage Report

Created: 2025-01-24 06:31

/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