FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

GitHub Viewer

/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2026 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 . */ #include "checkfunctions.h" #include "errortypes.h" #include "fixture.h" #include "helpers.h" #include "platform.h" #include "settings.h" #include "standards.h" #include #include class TestFunctions : public TestFixture { public: TestFunctions() : TestFixture("TestFunctions") {} private: const Settings settings = settingsBuilder().severity(Severity::style).severity(Severity::warning).severity(Severity::performance).severity(Severity::portability). certainty(Certainty::inconclusive).c(Standards::C11).cpp(Standards::CPP11).library("std.cfg").library("posix.cfg").build(); void run() override { mNewTemplate = true; // Prohibited functions TEST_CASE(prohibitedFunctions_posix); TEST_CASE(prohibitedFunctions_index); TEST_CASE(prohibitedFunctions_qt_index); // FP when using the Qt function 'index'? TEST_CASE(prohibitedFunctions_rindex); TEST_CASE(prohibitedFunctions_var); // no false positives for variables TEST_CASE(prohibitedFunctions_gets); // dangerous function TEST_CASE(prohibitedFunctions_alloca); TEST_CASE(prohibitedFunctions_declaredFunction); // declared function ticket #3121 TEST_CASE(prohibitedFunctions_std_gets); // test std::gets TEST_CASE(prohibitedFunctions_multiple); // multiple use of obsolete functions TEST_CASE(prohibitedFunctions_c_declaration); // c declared function TEST_CASE(prohibitedFunctions_functionWithBody); // function with body TEST_CASE(prohibitedFunctions_crypt); // Non-reentrant function TEST_CASE(prohibitedFunctions_namespaceHandling); // Invalid function usage TEST_CASE(invalidFunctionUsage1); TEST_CASE(invalidFunctionUsageStrings); // Invalid function argument TEST_CASE(invalidFunctionArg1); // Math function usage TEST_CASE(mathfunctionCall_fmod); TEST_CASE(mathfunctionCall_sqrt); TEST_CASE(mathfunctionCall_log); TEST_CASE(mathfunctionCall_acos); TEST_CASE(mathfunctionCall_asin); TEST_CASE(mathfunctionCall_pow); TEST_CASE(mathfunctionCall_atan2); TEST_CASE(mathfunctionCall_precision); // Ignored return value TEST_CASE(checkIgnoredReturnValue); TEST_CASE(checkIgnoredErrorCode); // memset.. TEST_CASE(memsetZeroBytes); TEST_CASE(memsetInvalid2ndParam); // missing "return" TEST_CASE(checkMissingReturn1); TEST_CASE(checkMissingReturn2); // #11798 TEST_CASE(checkMissingReturn3); TEST_CASE(checkMissingReturn4); TEST_CASE(checkMissingReturn5); TEST_CASE(checkMissingReturn6); // #13180 TEST_CASE(checkMissingReturn7); // #14370 - FN try/catch TEST_CASE(checkMissingReturn8); TEST_CASE(checkMissingReturn9); TEST_CASE(checkMissingReturnStdInt); // #14482 - FN std::int32_t // std::move for locar variable TEST_CASE(returnLocalStdMove1); TEST_CASE(returnLocalStdMove2); TEST_CASE(returnLocalStdMove3); TEST_CASE(returnLocalStdMove4); TEST_CASE(returnLocalStdMove5); TEST_CASE(negativeMemoryAllocationSizeError); // #389 TEST_CASE(checkLibraryMatchFunctions); TEST_CASE(checkUseStandardLibrary1); TEST_CASE(checkUseStandardLibrary2); TEST_CASE(checkUseStandardLibrary3); TEST_CASE(checkUseStandardLibrary4); TEST_CASE(checkUseStandardLibrary5); TEST_CASE(checkUseStandardLibrary6); TEST_CASE(checkUseStandardLibrary7); TEST_CASE(checkUseStandardLibrary8); TEST_CASE(checkUseStandardLibrary9); TEST_CASE(checkUseStandardLibrary10); TEST_CASE(checkUseStandardLibrary11); TEST_CASE(checkUseStandardLibrary12); TEST_CASE(checkUseStandardLibrary13); TEST_CASE(checkUseStandardLibrary14); } struct CheckOptions { bool cpp = true; }; #define check(...) check_(__FILE__, __LINE__, __VA_ARGS__) template void check_(const char* file, int line, const char (&code)[size], const CheckOptions& options = make_default_obj()) { check_(file, line, code, settings, options.cpp); } template void check_(const char* file, int line, const char (&code)[size], const Settings& s, bool cpp = true) { SimpleTokenizer tokenizer(s, *this, cpp); ASSERT_LOC(tokenizer.tokenize(code), file, line); CheckFunctions check; runChecks(check, tokenizer, *this); } void prohibitedFunctions_posix() { check("void f()\n" "{\n" " bsd_signal(SIGABRT, SIG_IGN);\n" "}\n"); ASSERT_EQUALS("[test.cpp:3:5]: (style) Obsolescent function 'bsd_signal' called. It is recommended to use 'sigaction' instead. [bsd_signalCalled]\n", errout_str()); check("int f()\n" "{\n" " int bsd_signal(0);\n" " return bsd_signal;\n" "}\n"); ASSERT_EQUALS("", errout_str()); check("void f()\n" "{\n" " struct hostent *hp;\n" " if(!hp = gethostbyname(\"127.0.0.1\")) {\n" " exit(1);\n" " }\n" "}\n"); ASSERT_EQUALS("[test.cpp:4:14]: (style) Obsolescent function 'gethostbyname' called. It is recommended to use 'getaddrinfo' instead. [gethostbynameCalled]\n", errout_str()); check("void f()\n" "{\n" " long addr;\n" " addr = inet_addr(\"127.0.0.1\");\n" " if(!hp = gethostbyaddr((char *) &addr, sizeof(addr), AF_INET)) {\n" " exit(1);\n" " }\n" "}\n"); ASSERT_EQUALS("[test.cpp:5:14]: (style) Obsolescent function 'gethostbyaddr' called. It is recommended to use 'getnameinfo' instead. [gethostbyaddrCalled]\n", errout_str()); check("void f()\n" "{\n" " usleep( 1000 );\n" "}\n"); ASSERT_EQUALS("[test.cpp:3:5]: (style) Obsolescent function 'usleep' called. It is recommended to use 'nanosleep' or 'setitimer' instead. [usleepCalled]\n", errout_str()); } void prohibitedFunctions_index() { check("namespace n1 {\n" " int index(){ return 1; };\n" "}\n" "int main()\n" "{\n" " n1::index();\n" " return 0;\n" "}\n"); ASSERT_EQUALS("", errout_str()); check("std::size_t f()\n" "{\n" " std::size_t index(0);\n" " index++;\n" " return index;\n" "}\n"); ASSERT_EQUALS("", errout_str()); check("int f()\n" "{\n" " return this->index();\n" "}\n"); ASSERT_EQUALS("", errout_str()); check("void f()\n" "{\n" " int index( 0 );\n" "}\n"); ASSERT_EQUALS("", errout_str()); check("const char f()\n" "{\n" " const char var[6] = \"index\";\n" " const char i = index(var, 0);\n" " return i;\n" "}\n"); ASSERT_EQUALS("[test.cpp:4:20]: (style) Obsolescent function 'index' called. It is recommended to use 'strchr' instead. [indexCalled]\n", errout_str()); } void prohibitedFunctions_qt_index() { check("void TDataModel::forceRowRefresh(int row) {\n" " emit dataChanged(index(row, 0), index(row, columnCount() - 1));\n" "}\n"); ASSERT_EQUALS( "[test.cpp:2:22]: (style) Obsolescent function 'index' called. It is recommended to use 'strchr' instead. [indexCalled]\n" "[test.cpp:2:37]: (style) Obsolescent function 'index' called. It is recommended to use 'strchr' instead. [indexCalled]\n", errout_str()); } void prohibitedFunctions_rindex() { check("void f()\n" "{\n" " int rindex( 0 );\n" "}\n"); ASSERT_EQUALS("", errout_str()); check("void f()\n" "{\n" " const char var[7] = \"rindex\";\n" " print(rindex(var, 0));\n" "}\n"); ASSERT_EQUALS("[test.cpp:4:11]: (style) Obsolescent function 'rindex' called. It is recommended to use 'strrchr' instead. [rindexCalled]\n", errout_str()); } void prohibitedFunctions_var() { check("class Fred {\n" "public:\n" " Fred() : index(0) { }\n" " int index;\n" "};\n"); ASSERT_EQUALS("", errout_str()); } void prohibitedFunctions_gets() { check("void f()\n" "{\n" " char *x = gets(a);\n" "}\n"); ASSERT_EQUALS("[test.cpp:3:15]: (warning) Obsolete function 'gets' called. It is recommended to use 'fgets' or 'gets_s' instead. [getsCalled]\n", errout_str()); check("void f()\n" "{\n" " foo(x, gets(a));\n" "}\n"); ASSERT_EQUALS("[test.cpp:3:12]: (warning) Obsolete function 'gets' called. It is recommended to use 'fgets' or 'gets_s' instead. [getsCalled]\n", errout_str()); } void prohibitedFunctions_alloca() { check("void f()\n" "{\n" " char *x = alloca(10);\n" "}\n"); // #4382 - there are no VLAs in C++ ASSERT_EQUALS("[test.cpp:3:15]: (warning) Obsolete function 'alloca' called. [allocaCalled]\n", errout_str()); check("void f()\n" "{\n" " char *x = alloca(10);\n" "}\n", dinit(CheckOptions, $.cpp = false)); ASSERT_EQUALS("[test.c:3:15]: (warning) Obsolete function 'alloca' called. In C99 and later it is recommended to use a variable length array instead. [allocaCalled]\n", errout_str()); const Settings s = settingsBuilder(settings).c(Standards::C89).cpp(Standards::CPP03).build(); check("void f()\n" "{\n" " char *x = alloca(10);\n" "}\n", s); // #4382 - there are no VLAs in C++ ASSERT_EQUALS("", errout_str()); check("void f()\n" "{\n" " char *x = alloca(10);\n" "}\n", s, false); // #7558 - no alternative to alloca in C89 ASSERT_EQUALS("", errout_str()); check("void f()\n" "{\n" " char *x = alloca(10);\n" "}\n", s, false); ASSERT_EQUALS("", errout_str()); } // ticket #3121 void prohibitedFunctions_declaredFunction() { check("int ftime ( int a )\n" "{\n" " return a;\n" "}\n" "int main ()\n" "{\n" " int b ; b = ftime ( 1 ) ;\n" " return 0 ;\n" "}\n"); ASSERT_EQUALS("", errout_str()); } // test std::gets void prohibitedFunctions_std_gets() { check("void f(char * str)\n" "{\n" " char *x = std::gets(str);\n" " char *y = gets(str);\n" "}\n"); ASSERT_EQUALS("[test.cpp:3:20]: (warning) Obsolete function 'gets' called. It is recommended to use 'fgets' or 'gets_s' instead. [getsCalled]\n" "[test.cpp:4:15]: (warning) Obsolete function 'gets' called. It is recommended to use 'fgets' or 'gets_s' instead. [getsCalled]\n", errout_str()); } // multiple use void prohibitedFunctions_multiple() { check("void f(char * str)\n" "{\n" " char *x = std::gets(str);\n" " usleep( 1000 );\n" "}\n"); ASSERT_EQUALS("[test.cpp:3:20]: (warning) Obsolete function 'gets' called. It is recommended to use 'fgets' or 'gets_s' instead. [getsCalled]\n" "[test.cpp:4:5]: (style) Obsolescent function 'usleep' called. It is recommended to use 'nanosleep' or 'setitimer' instead. [usleepCalled]\n", errout_str()); } void prohibitedFunctions_c_declaration() { check("char * gets ( char * c ) ;\n" "int main ()\n" "{\n" " char s [ 10 ] ;\n" " gets ( s ) ;\n" " return 0;\n" "}\n"); ASSERT_EQUALS("[test.cpp:5:5]: (warning) Obsolete function 'gets' called. It is recommended to use 'fgets' or 'gets_s' instead. [getsCalled]\n", errout_str()); check("int getcontext(ucontext_t *ucp);\n" "void f (ucontext_t *ucp)\n" "{\n" " getcontext ( ucp ) ;\n" "}\n"); ASSERT_EQUALS("[test.cpp:4:5]: (portability) Obsolescent function 'getcontext' called. Applications are recommended to be rewritten to use POSIX threads. [getcontextCalled]\n", errout_str()); } void prohibitedFunctions_functionWithBody() { check("char * gets ( char * c ) { return c; }\n" "int main ()\n" "{\n" " char s [ 10 ] ;\n" " gets ( s ) ;\n" " return 0;\n" "}\n"); ASSERT_EQUALS("", errout_str()); } void prohibitedFunctions_crypt() { check("void f(char *pwd)\n" "{\n" " char *cpwd;" " crypt(pwd, cpwd);\n" "}\n"); ASSERT_EQUALS("[test.cpp:3:20]: (warning) Return value of function crypt() is not used. [ignoredReturnValue]\n" "[test.cpp:3:20]: (portability) Non reentrant function 'crypt' called. For threadsafe applications it is recommended to use the reentrant replacement function 'crypt_r'. [cryptCalled]\n", errout_str()); check("void f()\n" "{\n" " char *pwd = getpass(\"Password:\");" " char *cpwd;" " crypt(pwd, cpwd);\n" "}\n"); ASSERT_EQUALS("[test.cpp:3:57]: (warning) Return value of function crypt() is not used. [ignoredReturnValue]\n" "[test.cpp:3:57]: (portability) Non reentrant function 'crypt' called. For threadsafe applications it is recommended to use the reentrant replacement function 'crypt_r'. [cryptCalled]\n", errout_str()); check("int f()\n" "{\n" " int crypt = 0;" " return crypt;\n" "}\n"); ASSERT_EQUALS("", errout_str()); } void prohibitedFunctions_namespaceHandling() { check("void f()\n" "{\n" " time_t t = 0;" " auto lt = std::localtime(&t);\n" "}\n"); ASSERT_EQUALS("[test.cpp:3:37]: (portability) Non reentrant function 'localtime' called. For threadsafe applications it is recommended to use the reentrant replacement function 'localtime_r'. [localtimeCalled]\n", errout_str()); // Passed as function argument check("void f()\n" "{\n" " printf(\"Magic guess: %d\", getpwent());\n" "}\n"); ASSERT_EQUALS("[test.cpp:3:31]: (portability) Non reentrant function 'getpwent' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getpwent_r'. [getpwentCalled]\n", errout_str()); // Pass return value check("void f()\n" "{\n" " time_t t = 0;" " struct tm *foo = localtime(&t);\n" "}\n"); ASSERT_EQUALS("[test.cpp:3:39]: (portability) Non reentrant function 'localtime' called. For threadsafe applications it is recommended to use the reentrant replacement function 'localtime_r'. [localtimeCalled]\n", errout_str()); // Access via global namespace check("void f()\n" "{\n" " ::getpwent();\n" "}\n"); ASSERT_EQUALS("[test.cpp:3:7]: (warning) Return value of function ::getpwent() is not used. [ignoredReturnValue]\n" "[test.cpp:3:7]: (portability) Non reentrant function 'getpwent' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getpwent_r'. [getpwentCalled]\n", errout_str()); // Be quiet on function definitions check("int getpwent()\n" "{\n" " return 123;\n" "}\n"); ASSERT_EQUALS("", errout_str()); // Be quiet on other namespaces check("void f()\n" "{\n" " foobar::getpwent();\n" "}\n"); ASSERT_EQUALS("", errout_str()); // Be quiet on class member functions check("void f()\n" "{\n" " foobar.getpwent();\n" "}\n"); ASSERT_EQUALS("", errout_str()); } void invalidFunctionUsage1() { check("void f() { memset(a,b,sizeof(a)!=12); }\n"); ASSERT_EQUALS("[test.cpp:1:32]: (error) Invalid memset() argument nr 3. A non-boolean value is required. [invalidFunctionArgBool]\n", errout_str()); check("void f() { memset(a,b,sizeof(a)!=0); }\n"); ASSERT_EQUALS("[test.cpp:1:32]: (error) Invalid memset() argument nr 3. A non-boolean value is required. [invalidFunctionArgBool]\n", errout_str()); check("void f() { memset(a,b,!c); }\n"); ASSERT_EQUALS("[test.cpp:1:23]: (error) Invalid memset() argument nr 3. A non-boolean value is required. [invalidFunctionArgBool]\n", errout_str()); // Ticket #6990 check("void f(bool c) { memset(a,b,c); }\n"); ASSERT_EQUALS("[test.cpp:1:29]: (error) Invalid memset() argument nr 3. A non-boolean value is required. [invalidFunctionArgBool]\n", errout_str()); check("void f() { memset(a,b,true); }\n"); ASSERT_EQUALS("[test.cpp:1:23]: (error) Invalid memset() argument nr 3. A non-boolean value is required. [invalidFunctionArgBool]\n", errout_str()); // Ticket #6588 (c mode) check("void record(char* buf, int n) {\n" " memset(buf, 0, n < 255);\n" /* KO */ " memset(buf, 0, n < 255 ? n : 255);\n" /* OK */ "}\n", dinit(CheckOptions, $.cpp = false)); ASSERT_EQUALS("[test.c:2:20]: (error) Invalid memset() argument nr 3. A non-boolean value is required. [invalidFunctionArgBool]\n", errout_str()); // Ticket #6588 (c++ mode) check("void record(char* buf, int n) {\n" " memset(buf, 0, n < 255);\n" /* KO */ " memset(buf, 0, n < 255 ? n : 255);\n" /* OK */ "}\n"); ASSERT_EQUALS("[test.cpp:2:20]: (error) Invalid memset() argument nr 3. A non-boolean value is required. [invalidFunctionArgBool]\n", errout_str()); check("int boolArgZeroIsInvalidButOneIsValid(int a, int param) {\n" " return div(a, param > 0);\n" "}\n"); ASSERT_EQUALS("[test.cpp:2:23]: (error) Invalid div() argument nr 2. The value is 0 or 1 (boolean) but the valid values are ':-1,1:'. [invalidFunctionArg]\n", errout_str()); check("void boolArgZeroIsValidButOneIsInvalid(int param) {\n" " strtol(a, b, param > 0);\n" "}\n"); ASSERT_EQUALS("[test.cpp:2:22]: (error) Invalid strtol() argument nr 3. The value is 0 or 1 (boolean) but the valid values are '0,2:36'. [invalidFunctionArg]\n", errout_str()); check("void f() { strtol(a,b,1); }\n"); ASSERT_EQUALS("[test.cpp:1:23]: (error) Invalid strtol() argument nr 3. The value is 1 but the valid values are '0,2:36'. [invalidFunctionArg]\n", errout_str()); check("void f() { strtol(a,b,10); }\n"); ASSERT_EQUALS("", errout_str()); check("void f(std::vector& v) {\n" // #10754 " int N = -1;\n" " for (long i = 0; i < g(); i++)\n" " N = h(N);\n" " v.resize(N);\n" "}\n"); ASSERT_EQUALS("[test.cpp:5:14]: (warning) Invalid v.resize() argument nr 1. The value is -1 but the valid values are '0:'. [invalidFunctionArg]\n", errout_str()); check("void f(std::vector& v, int N) {\n" " if (N < -1)\n" " return;\n" " v.resize(N);\n" "}\n"); ASSERT_EQUALS("[test.cpp:2:11] -> [test.cpp:4:14]: (warning) Either the condition 'N

Back | FazBrowse Home | New Git URL