Restored files removed in 1cc872f5b2

This commit is contained in:
PKEuS 2014-09-23 21:00:23 +02:00
parent 8ccf9eed09
commit 6dc5b1725e
3 changed files with 535 additions and 0 deletions

View File

@ -0,0 +1,79 @@
/*
* Cppcheck - A tool for static C/C++ code analysis
* Copyright (C) 2007-2014 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/>.
*/
//---------------------------------------------------------------------------
// Obsolete functions
//---------------------------------------------------------------------------
#include "checkobsolescentfunctions.h"
#include "symboldatabase.h"
//---------------------------------------------------------------------------
// Register this check class (by creating a static instance of it)
namespace {
CheckObsoleteFunctions instance;
}
void CheckObsoleteFunctions::obsoleteFunctions()
{
if (!_settings->isEnabled("style"))
return;
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
// Functions defined somewhere?
for (unsigned int i = 0; i < symbolDatabase->functionScopes.size(); i++) {
const Scope* scope = symbolDatabase->functionScopes[i];
_obsoleteStandardFunctions.erase(scope->className);
_obsoletePosixFunctions.erase(scope->className);
_obsoleteC99Functions.erase(scope->className);
}
for (unsigned int i = 0; i < symbolDatabase->functionScopes.size(); i++) {
const Scope* scope = symbolDatabase->functionScopes[i];
for (const Token* tok = scope->classStart; tok != scope->classEnd; tok = tok->next()) {
if (tok->isName() && tok->varId()==0 && (tok->next() && tok->next()->str() == "(") &&
(!Token::Match(tok->previous(), ".|::") || Token::simpleMatch(tok->tokAt(-2), "std ::"))) {
std::map<std::string,std::string>::const_iterator it = _obsoleteStandardFunctions.find(tok->str());
if (it != _obsoleteStandardFunctions.end()) {
// If checking an old code base it might be uninteresting to update obsolete functions.
reportError(tok, Severity::style, "obsoleteFunctions"+it->first, it->second);
} else {
if (_settings->standards.posix) {
it = _obsoletePosixFunctions.find(tok->str());
if (it != _obsoletePosixFunctions.end()) {
// If checking an old code base it might be uninteresting to update obsolete functions.
reportError(tok, Severity::style, "obsoleteFunctions"+it->first, it->second);
}
}
if (_settings->standards.c >= Standards::C99) {
// alloca : this function is obsolete in C but not in C++ (#4382)
it = _obsoleteC99Functions.find(tok->str());
if (it != _obsoleteC99Functions.end() && !(tok->str() == "alloca" && _tokenizer->isCPP())) {
reportError(tok, Severity::style, "obsoleteFunctions"+it->first, it->second);
}
}
}
}
}
}
}
//---------------------------------------------------------------------------

View File

@ -0,0 +1,149 @@
/*
* Cppcheck - A tool for static C/C++ code analysis
* Copyright (C) 2007-2014 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 checkobsoletefunctionsH
#define checkobsoletefunctionsH
//---------------------------------------------------------------------------
#include "config.h"
#include "check.h"
#include <string>
#include <map>
/// @addtogroup Checks
/// @{
/**
* @brief Using obsolete functions that are always insecure to use.
*/
class CPPCHECKLIB CheckObsoleteFunctions : public Check {
public:
/** This constructor is used when registering the CheckObsoleteFunctions */
CheckObsoleteFunctions() : Check(myName()) {
initObsoleteFunctions();
}
/** This constructor is used when running checks. */
CheckObsoleteFunctions(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
: Check(myName(), tokenizer, settings, errorLogger) {
initObsoleteFunctions();
}
void runSimplifiedChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) {
CheckObsoleteFunctions checkObsoleteFunctions(tokenizer, settings, errorLogger);
checkObsoleteFunctions.obsoleteFunctions();
}
/** Check for obsolete functions */
void obsoleteFunctions();
private:
/* function name / error message */
std::map<std::string, std::string> _obsoleteStandardFunctions;
std::map<std::string, std::string> _obsoletePosixFunctions;
std::map<std::string, std::string> _obsoleteC99Functions;
/** init obsolete functions list ' */
void initObsoleteFunctions() {
// Obsolete posix functions, which messages suggest only one alternative and doesn't contain additional information.
const struct {
const char* bad;
const char* good;
} posix_stdmsgs[] = {
{"bsd_signal", "sigaction"},
{"gethostbyaddr", "getnameinfo"},
{"gethostbyname", "getaddrinfo"},
{"bcmp", "memcmp"},
{"bzero", "memset"},
{"ecvt", "sprintf"},
{"fcvt", "sprintf"},
{"gcvt", "sprintf"},
{"getwd", "getcwd"},
{"index", "strchr"}, // See #2334 (using the Qt Model/View function 'index')
{"rindex", "strrchr"},
{"pthread_attr_getstackaddr", "pthread_attr_getstack"},
{"pthread_attr_setstackaddr", "pthread_attr_setstack"},
{"vfork", "fork"},
{"wcswcs", "wcsstr"},
{"rand_r", "rand"},
{"utime", "utimensat"},
{"asctime_r", "strftime"},
{"ctime_r", "strftime"}
};
for (std::size_t i = 0; i < (sizeof(posix_stdmsgs) / sizeof(*posix_stdmsgs)); ++i) {
_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.";
}
_obsoletePosixFunctions["usleep"] = "Obsolete function 'usleep' called. It is recommended to use the 'nanosleep' or 'setitimer' function instead.\n"
"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.";
_obsoletePosixFunctions["bcopy"] = "Obsolete function 'bcopy' called. It is recommended to use the 'memmove' or 'memcpy' function instead.";
_obsoletePosixFunctions["ftime"] = "Obsolete function 'ftime' called. It is recommended to use time(), gettimeofday() or clock_gettime() instead.";
_obsoletePosixFunctions["getcontext"] = "Obsolete function 'getcontext' called. Due to portability issues, applications are recommended to be rewritten to use POSIX threads.";
_obsoletePosixFunctions["makecontext"] = "Obsolete function 'makecontext' called. Due to portability issues, applications are recommended to be rewritten to use POSIX threads.";
_obsoletePosixFunctions["swapcontext"] = "Obsolete function 'swapcontext' called. Due to portability issues, applications are recommended to be rewritten to use POSIX threads.";
_obsoletePosixFunctions["scalbln"] = "Obsolete function 'scalb' called. It is recommended to use 'scalbln', 'scalblnf' or 'scalblnl' instead.";
_obsoletePosixFunctions["ualarm"] = "Obsolete function 'ualarm' called. It is recommended to use 'timer_create', 'timer_delete', 'timer_getoverrun', 'timer_gettime' or 'timer_settime' instead.";
_obsoletePosixFunctions["tmpnam"] = "Obsolete function 'tmpnam' called. It is recommended to use 'tmpfile', 'mkstemp' or 'mkdtemp' instead.";
_obsoletePosixFunctions["tmpnam_r"] = "Obsolete function 'tmpnam_r' called. It is recommended to use 'tmpfile', 'mkstemp' or 'mkdtemp' instead.";
_obsoleteStandardFunctions["gets"] = "Obsolete function 'gets' called. It is recommended to use the function 'fgets' instead.\n"
"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.";
_obsoleteC99Functions["alloca"] = "Obsolete function 'alloca' called. In C99 and later it is recommended to use a variable length array instead.\n"
"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).";
_obsoleteC99Functions["asctime"] = "Obsolete function 'asctime' called. It is recommended to use the function 'strftime' instead.";
// ctime is obsolete - it's not threadsafe. but there is no good replacement.
//_obsoleteC99Functions["ctime"] = "Obsolete function 'ctime' called. It is recommended to use the function 'strftime' instead.";
}
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const {
CheckObsoleteFunctions c(0, settings, errorLogger);
std::map<std::string,std::string>::const_iterator it(_obsoletePosixFunctions.begin()), itend(_obsoletePosixFunctions.end());
for (; it!=itend; ++it) {
c.reportError(0, Severity::style, "obsoleteFunctions"+it->first, it->second);
}
}
static std::string myName() {
return "Obsolete functions";
}
std::string classInfo() const {
std::string info = "Warn if any of these obsolete functions are used:\n";
std::map<std::string,std::string>::const_iterator it(_obsoletePosixFunctions.begin()), itend(_obsoletePosixFunctions.end());
for (; it!=itend; ++it) {
info += "* " + it->first + "\n";
}
return info;
}
};
/// @}
//---------------------------------------------------------------------------
#endif // checkobsoletefunctionsH

View File

@ -0,0 +1,307 @@
/*
* Cppcheck - A tool for static C/C++ code analysis
* Copyright (C) 2007-2014 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/>.
*/
#include "tokenize.h"
#include "checkobsolescentfunctions.h"
#include "testsuite.h"
#include <sstream>
extern std::ostringstream errout;
class TestObsoleteFunctions : public TestFixture {
public:
TestObsoleteFunctions() : TestFixture("TestObsoleteFunctions") {
}
private:
void run() {
TEST_CASE(testbsd_signal);
TEST_CASE(testgethostbyname);
TEST_CASE(testgethostbyaddr);
TEST_CASE(testusleep);
TEST_CASE(testindex);
TEST_CASE(test_qt_index); // FP when using the Qt function 'index'?
TEST_CASE(testrindex);
// no false positives for variables
TEST_CASE(testvar);
// dangerous function
TEST_CASE(testgets);
TEST_CASE(testalloca);
// declared function ticket #3121
TEST_CASE(test_declared_function);
// test std::gets
TEST_CASE(test_std_gets);
// multiple use of obsolete functions
TEST_CASE(test_multiple);
// c declared function
TEST_CASE(test_c_declaration);
// function with body
TEST_CASE(test_function_with_body);
// null pointer dereference in obsoleteFunctions
TEST_CASE(ticket3238);
}
void check(const char code[], const char filename[]="test.cpp") {
// Clear the error buffer..
errout.str("");
Settings settings;
settings.addEnabled("style");
settings.standards.posix = true;
settings.standards.c = Standards::C11;
// Tokenize..
Tokenizer tokenizer(&settings, this);
std::istringstream istr(code);
tokenizer.tokenize(istr, filename);
tokenizer.simplifyTokenList2();
// Check for obsolete functions..
CheckObsoleteFunctions checkObsoleteFunctions(&tokenizer, &settings, this);
checkObsoleteFunctions.obsoleteFunctions();
}
void testbsd_signal() {
check("void f()\n"
"{\n"
" bsd_signal(SIGABRT, SIG_IGN);\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (style) Obsolete function 'bsd_signal' called. It is recommended to use the function 'sigaction' instead.\n", errout.str());
check("int f()\n"
"{\n"
" int bsd_signal(0);\n"
" return bsd_signal;\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void testgethostbyname() {
check("void f()\n"
"{\n"
" struct hostent *hp;\n"
" if(!hp = gethostbyname('127.0.0.1')) {\n"
" exit(1);\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (style) Obsolete function 'gethostbyname' called. It is recommended to use the function 'getaddrinfo' instead.\n", errout.str());
}
void testgethostbyaddr() {
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"
"}");
ASSERT_EQUALS("[test.cpp:5]: (style) Obsolete function 'gethostbyaddr' called. It is recommended to use the function 'getnameinfo' instead.\n", errout.str());
}
void testusleep() {
check("void f()\n"
"{\n"
" usleep( 1000 );\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (style) Obsolete function 'usleep' called. It is recommended to use the 'nanosleep' or 'setitimer' function instead.\n", errout.str());
}
void testindex() {
check("namespace n1 {\n"
" int index(){};\n"
"}\n"
"int main()\n"
"{\n"
" n1::index();\n"
"}");
ASSERT_EQUALS("", errout.str());
check("std::size_t f()\n"
"{\n"
" std::size_t index(0);\n"
" index++;\n"
" return index;\n"
"}");
ASSERT_EQUALS("", errout.str());
check("int f()\n"
"{\n"
" return this->index();\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void f()\n"
"{\n"
" int index( 0 );\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"
"}");
ASSERT_EQUALS("[test.cpp:4]: (style) Obsolete function 'index' called. It is recommended to use the function 'strchr' instead.\n",
errout.str());
}
void test_qt_index() {
check("void TDataModel::forceRowRefresh(int row) {\n"
" emit dataChanged(index(row, 0), index(row, columnCount() - 1));\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (style) Obsolete function 'index' called. It is recommended to use the function 'strchr' instead.\n", errout.str());
}
void testrindex() {
check("void f()\n"
"{\n"
" int rindex( 0 );\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void f()\n"
"{\n"
" const char var[7] = 'rindex';\n"
" print(rindex(var, 0));\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (style) Obsolete function 'rindex' called. It is recommended to use the function 'strrchr' instead.\n", errout.str());
}
void testvar() {
check("class Fred {\n"
"public:\n"
" Fred() : index(0) { }\n"
" int index;\n"
"};");
ASSERT_EQUALS("", errout.str());
}
void testgets() {
check("void f()\n"
"{\n"
" char *x = gets();\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (style) Obsolete function 'gets' called. It is recommended to use the function 'fgets' instead.\n", errout.str());
check("void f()\n"
"{\n"
" foo(x, gets());\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (style) Obsolete function 'gets' called. It is recommended to use the function 'fgets' instead.\n", errout.str());
}
void testalloca() {
check("void f()\n"
"{\n"
" char *x = alloca(10);\n"
"}\n", "test.cpp"); // #4382 - there are no VLAs in C++
ASSERT_EQUALS("", errout.str());
check("void f()\n"
"{\n"
" char *x = alloca(10);\n"
"}\n", "test.c");
ASSERT_EQUALS("[test.c:3]: (style) Obsolete function 'alloca' called. In C99 and later it is recommended to use a variable length array instead.\n", errout.str());
}
// ticket #3121
void test_declared_function() {
check("int ftime ( int a )\n"
"{\n"
" return a;\n"
"}\n"
"int main ()\n"
"{\n"
" int b ; b = ftime ( 1 ) ;\n"
" return 0 ;\n"
"}");
ASSERT_EQUALS("", errout.str());
}
// test std::gets
void test_std_gets() {
check("void f(char * str)\n"
"{\n"
" char *x = std::gets(str);\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (style) Obsolete function 'gets' called. It is recommended to use the function 'fgets' instead.\n", errout.str());
}
// multiple use
void test_multiple() {
check("void f(char * str)\n"
"{\n"
" char *x = std::gets(str);\n"
" usleep( 1000 );\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (style) Obsolete function 'gets' called. It is recommended to use the function 'fgets' instead.\n"
"[test.cpp:4]: (style) Obsolete function 'usleep' called. It is recommended to use the 'nanosleep' or 'setitimer' function instead.\n", errout.str());
}
void test_c_declaration() {
check("char * gets ( char * c ) ;\n"
"int main ()\n"
"{\n"
" char s [ 10 ] ;\n"
" gets ( s ) ;\n"
"}");
ASSERT_EQUALS("[test.cpp:5]: (style) Obsolete function 'gets' called. It is recommended to use the function 'fgets' instead.\n", errout.str());
check("int getcontext(ucontext_t *ucp);\n"
"int f (ucontext_t *ucp)\n"
"{\n"
" getcontext ( ucp ) ;\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (style) Obsolete function 'getcontext' called. Due to portability issues, applications are recommended to be rewritten to use POSIX threads.\n", errout.str());
}
void test_function_with_body() {
check("char * gets ( char * c ) { return c; }\n"
"int main ()\n"
"{\n"
" char s [ 10 ] ;\n"
" gets ( s ) ;\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void ticket3238() {
check("__FBSDID(\"...\");\n");
ASSERT_EQUALS("", errout.str());
}
};
REGISTER_TEST(TestObsoleteFunctions)