Cppcheck
checkobsoletefunctions.h
Go to the documentation of this file.
00001 /*
00002  * Cppcheck - A tool for static C/C++ code analysis
00003  * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team.
00004  *
00005  * This program is free software: you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation, either version 3 of the License, or
00008  * (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00017  */
00018 
00019 
00020 //---------------------------------------------------------------------------
00021 #ifndef CheckObsoleteFunctionsH
00022 #define CheckObsoleteFunctionsH
00023 //---------------------------------------------------------------------------
00024 
00025 #include "config.h"
00026 #include "check.h"
00027 #include <string>
00028 #include <map>
00029 
00030 
00031 /// @addtogroup Checks
00032 /// @{
00033 
00034 /**
00035  * @brief Using obsolete functions that are always insecure to use.
00036  */
00037 
00038 class CPPCHECKLIB CheckObsoleteFunctions : public Check {
00039 public:
00040     /** This constructor is used when registering the CheckObsoleteFunctions */
00041     CheckObsoleteFunctions() : Check(myName()) {
00042         initObsoleteFunctions();
00043     }
00044 
00045     /** This constructor is used when running checks. */
00046     CheckObsoleteFunctions(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
00047         : Check(myName(), tokenizer, settings, errorLogger) {
00048         initObsoleteFunctions();
00049     }
00050 
00051     void runSimplifiedChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) {
00052         CheckObsoleteFunctions checkObsoleteFunctions(tokenizer, settings, errorLogger);
00053         checkObsoleteFunctions.obsoleteFunctions();
00054     }
00055 
00056     /** Check for obsolete functions */
00057     void obsoleteFunctions();
00058 
00059 private:
00060     /* function name / error message */
00061     std::map<std::string, std::string> _obsoleteStandardFunctions;
00062     std::map<std::string, std::string> _obsoletePosixFunctions;
00063     std::map<std::string, std::string> _obsoleteC99Functions;
00064 
00065     /** init obsolete functions list ' */
00066     void initObsoleteFunctions() {
00067         // Obsolete posix functions, which messages suggest only one alternative and doesn't contain additional information.
00068         const struct {
00069             const char* bad;
00070             const char* good;
00071         } posix_stdmsgs[] = {
00072             {"bsd_signal", "sigaction"},
00073             {"gethostbyaddr", "getnameinfo"},
00074             {"gethostbyname", "getaddrinfo"},
00075             {"bcmp", "memcmp"},
00076             {"bzero", "memset"},
00077             {"ecvt", "sprintf"},
00078             {"fcvt", "sprintf"},
00079             {"gcvt", "sprintf"},
00080             {"getwd", "getcwd"},
00081             {"index", "strchr"}, // See #2334 (using the Qt Model/View function 'index')
00082             {"rindex", "strrchr"},
00083             {"pthread_attr_getstackaddr", "pthread_attr_getstack"},
00084             {"pthread_attr_setstackaddr", "pthread_attr_setstack"},
00085             {"vfork", "fork"},
00086             {"wcswcs", "wcsstr"},
00087             {"rand_r", "rand"},
00088             {"utime", "utimensat"},
00089             {"asctime_r", "strftime"},
00090             {"ctime_r", "strftime"}
00091         };
00092 
00093         for (std::size_t i = 0; i < (sizeof(posix_stdmsgs) / sizeof(*posix_stdmsgs)); ++i) {
00094             _obsoletePosixFunctions[posix_stdmsgs[i].bad] = "Obsolete function '" + std::string(posix_stdmsgs[i].bad) + "' called. It is recommended to use the function '" + posix_stdmsgs[i].good + "' instead.";
00095         }
00096 
00097         _obsoletePosixFunctions["usleep"] = "Obsolete function 'usleep' called. It is recommended to use the 'nanosleep' or 'setitimer' function instead.\n"
00098                                             "The obsolete function 'usleep' is called. POSIX.1-2001 declares usleep() function obsolete and POSIX.1-2008 removes it. It is recommended that new applications use the 'nanosleep' or 'setitimer' function.";
00099 
00100         _obsoletePosixFunctions["bcopy"] = "Obsolete function 'bcopy' called. It is recommended to use the 'memmove' or 'memcpy' function instead.";
00101 
00102         _obsoletePosixFunctions["ftime"] = "Obsolete function 'ftime' called. It is recommended to use time(), gettimeofday() or clock_gettime() instead.";
00103 
00104         _obsoletePosixFunctions["getcontext"] = "Obsolete function 'getcontext' called. Due to portability issues, applications are recommended to be rewritten to use POSIX threads.";
00105         _obsoletePosixFunctions["makecontext"] = "Obsolete function 'makecontext' called. Due to portability issues, applications are recommended to be rewritten to use POSIX threads.";
00106         _obsoletePosixFunctions["swapcontext"] = "Obsolete function 'swapcontext' called. Due to portability issues, applications are recommended to be rewritten to use POSIX threads.";
00107 
00108         _obsoletePosixFunctions["scalbln"] = "Obsolete function 'scalb' called. It is recommended to use 'scalbln', 'scalblnf' or 'scalblnl' instead.";
00109 
00110         _obsoletePosixFunctions["ualarm"] = "Obsolete function 'ualarm' called. It is recommended to use 'timer_create', 'timer_delete', 'timer_getoverrun', 'timer_gettime' or 'timer_settime' instead.";
00111 
00112         _obsoletePosixFunctions["tmpnam"] = "Obsolete function 'tmpnam' called. It is recommended to use 'tmpfile', 'mkstemp' or 'mkdtemp' instead.";
00113 
00114         _obsoletePosixFunctions["tmpnam_r"] = "Obsolete function 'tmpnam_r' called. It is recommended to use 'tmpfile', 'mkstemp' or 'mkdtemp' instead.";
00115 
00116         _obsoleteStandardFunctions["gets"] = "Obsolete function 'gets' called. It is recommended to use the function 'fgets' instead.\n"
00117                                              "The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun if the input data exceeds the size of the buffer. It is recommended to use the function 'fgets' instead.";
00118         _obsoleteC99Functions["alloca"] = "Obsolete function 'alloca' called. In C99 and later it is recommended to use a variable length array instead.\n"
00119                                           "The obsolete function 'alloca' is called. In C99 and later it is recommended to use a variable length array or a dynamically allocated array instead. The function 'alloca' is dangerous for many reasons (http://stackoverflow.com/questions/1018853/why-is-alloca-not-considered-good-practice and http://linux.die.net/man/3/alloca).";
00120         _obsoleteC99Functions["asctime"] = "Obsolete function 'asctime' called. It is recommended to use the function 'strftime' instead.";
00121         // ctime is obsolete - it's not threadsafe. but there is no good replacement.
00122         //_obsoleteC99Functions["ctime"] = "Obsolete function 'ctime' called. It is recommended to use the function 'strftime' instead.";
00123     }
00124 
00125     void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const {
00126         CheckObsoleteFunctions c(0, settings, errorLogger);
00127 
00128         std::map<std::string,std::string>::const_iterator it(_obsoletePosixFunctions.begin()), itend(_obsoletePosixFunctions.end());
00129         for (; it!=itend; ++it) {
00130             c.reportError(0, Severity::style, "obsoleteFunctions"+it->first, it->second);
00131         }
00132     }
00133 
00134     static std::string myName() {
00135         return "Obsolete functions";
00136     }
00137 
00138     std::string classInfo() const {
00139         std::string info = "Warn if any of these obsolete functions are used:\n";
00140         std::map<std::string,std::string>::const_iterator it(_obsoletePosixFunctions.begin()), itend(_obsoletePosixFunctions.end());
00141         for (; it!=itend; ++it) {
00142             info += "* " + it->first + "\n";
00143         }
00144         return info;
00145     }
00146 };
00147 /// @}
00148 //---------------------------------------------------------------------------
00149 #endif