Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 136 lines (116 sloc) 5.825 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
/*
* Cppcheck - A tool for static C/C++ code analysis
* Copyright (C) 2007-2012 Daniel Marjamäki and Cppcheck team.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

//---------------------------------------------------------------------------
#ifndef CheckIOH
#define CheckIOH
//---------------------------------------------------------------------------

#include "check.h"
#include "config.h"

class Variable;

/// @addtogroup Checks
/// @{

/** @brief %Check input output operations. */
class CPPCHECKLIB CheckIO : public Check {
public:
    /** @brief This constructor is used when registering CheckIO */
    CheckIO() : Check(myName())
    { }

    /** @brief This constructor is used when running checks. */
    CheckIO(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
        : Check(myName(), tokenizer, settings, errorLogger)
    { }

    /** @brief Run checks on the normal token list */
    void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) {
        CheckIO checkIO(tokenizer, settings, errorLogger);

        checkIO.checkWrongPrintfScanfArguments();
    }

    /** @brief Run checks on the simplified token list */
    void runSimplifiedChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) {
        CheckIO checkIO(tokenizer, settings, errorLogger);

        checkIO.checkCoutCerrMisusage();
        checkIO.checkFileUsage();
        checkIO.invalidScanf();
    }

    /** @brief %Check for missusage of std::cout */
    void checkCoutCerrMisusage();

    /** @brief %Check usage of files*/
    void checkFileUsage();

    /** @brief scanf can crash if width specifiers are not used */
    void invalidScanf();

    /** @brief %Checks type and number of arguments given to functions like printf or scanf*/
    void checkWrongPrintfScanfArguments();

private:
    // Reporting errors..
    void coutCerrMisusageError(const Token* tok, const std::string& streamName);
    void fflushOnInputStreamError(const Token *tok, const std::string &varname);
    void ioWithoutPositioningError(const Token *tok);
    void readWriteOnlyFileError(const Token *tok);
    void writeReadOnlyFileError(const Token *tok);
    void useClosedFileError(const Token *tok);
    void invalidScanfError(const Token *tok, bool portability);
    void wrongPrintfScanfArgumentsError(const Token* tok,
                                        const std::string &function,
                                        unsigned int numFormat,
                                        unsigned int numFunction);
    void invalidScanfArgTypeError(const Token* tok, const std::string &functionName, unsigned int numFormat);
    void invalidPrintfArgTypeError_s(const Token* tok, unsigned int numFormat);
    void invalidPrintfArgTypeError_n(const Token* tok, unsigned int numFormat);
    void invalidPrintfArgTypeError_p(const Token* tok, unsigned int numFormat);
    void invalidPrintfArgTypeError_int(const Token* tok, unsigned int numFormat, char c);
    void invalidPrintfArgTypeError_uint(const Token* tok, unsigned int numFormat, char c);
    void invalidPrintfArgTypeError_sint(const Token* tok, unsigned int numFormat, char c);
    void invalidPrintfArgTypeError_float(const Token* tok, unsigned int numFormat, char c);
    void invalidScanfFormatWidthError(const Token* tok, unsigned int numFormat, int width, const Variable *var);

    void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const {
        CheckIO c(0, settings, errorLogger);

        c.coutCerrMisusageError(0, "cout");
        c.fflushOnInputStreamError(0, "stdin");
        c.ioWithoutPositioningError(0);
        c.readWriteOnlyFileError(0);
        c.writeReadOnlyFileError(0);
        c.useClosedFileError(0);
        c.invalidScanfError(0, false);
        c.wrongPrintfScanfArgumentsError(0,"printf",3,2);
        c.invalidScanfArgTypeError(0, "scanf", 1);
        c.invalidPrintfArgTypeError_s(0, 1);
        c.invalidPrintfArgTypeError_n(0, 1);
        c.invalidPrintfArgTypeError_p(0, 1);
        c.invalidPrintfArgTypeError_int(0, 1, 'X');
        c.invalidPrintfArgTypeError_uint(0, 1, 'u');
        c.invalidPrintfArgTypeError_sint(0, 1, 'i');
        c.invalidPrintfArgTypeError_float(0, 1, 'f');
        c.invalidScanfFormatWidthError(0, 10, 5, NULL);
    }

    static std::string myName() {
        return "IO";
    }

    std::string classInfo() const {
        return "Check input/output operations.\n"
               "* Bad usage of the function 'sprintf' (overlapping data)\n"
               "* Missing or wrong width specifiers in 'scanf' format string\n"
               "* Use a file that has been closed\n"
               "* File input/output without positioning results in undefined behaviour\n"
               "* Read to a file that has only been opened for writing (or vice versa)\n"
               "* Using fflush() on an input stream\n"
               "* Invalid usage of output stream. For example: 'std::cout << std::cout;'\n"
               "* Wrong number of arguments given to 'printf' or 'scanf;'\n";
    }
};
/// @}
//---------------------------------------------------------------------------
#endif
Something went wrong with that request. Please try again.