2008-12-19 22:15:18 +01:00
/*
2009-01-21 21:04:20 +01:00
* Cppcheck - A tool for static C / C + + code analysis
2009-05-30 07:48:12 +02:00
* Copyright ( C ) 2007 - 2009 Daniel Marjamäki and Cppcheck team .
2008-12-19 22:15:18 +01:00
*
* 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
2009-09-27 17:08:31 +02:00
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
2008-12-19 22:15:18 +01:00
*/
2009-01-06 15:18:36 +01:00
# include "../src/tokenize.h"
# include "../src/checkother.h"
2008-12-19 22:15:18 +01:00
# include "testsuite.h"
# include <sstream>
extern std : : ostringstream errout ;
class TestOther : public TestFixture
{
public :
TestOther ( ) : TestFixture ( " TestOther " )
{ }
private :
void run ( )
{
2009-03-28 07:49:47 +01:00
TEST_CASE ( zeroDiv1 ) ;
TEST_CASE ( zeroDiv2 ) ;
2009-08-23 05:34:19 +02:00
TEST_CASE ( zeroDiv3 ) ;
2009-08-30 21:02:09 +02:00
TEST_CASE ( zeroDiv4 ) ;
2009-03-28 07:49:47 +01:00
2009-01-05 16:49:57 +01:00
TEST_CASE ( delete1 ) ;
TEST_CASE ( delete2 ) ;
2009-01-08 22:08:14 +01:00
2009-01-18 22:19:02 +01:00
TEST_CASE ( unreachable1 ) ;
2009-01-15 17:57:51 +01:00
TEST_CASE ( sprintf1 ) ; // Dangerous usage of sprintf
2009-01-10 12:19:17 +01:00
TEST_CASE ( sprintf2 ) ;
2009-01-10 15:29:59 +01:00
TEST_CASE ( sprintf3 ) ;
2009-01-15 17:57:51 +01:00
TEST_CASE ( sprintf4 ) ; // struct member
TEST_CASE ( strPlusChar1 ) ; // "/usr" + '/'
2009-01-15 18:12:33 +01:00
TEST_CASE ( strPlusChar2 ) ; // "/usr" + ch
2009-01-18 18:42:41 +01:00
TEST_CASE ( strPlusChar3 ) ; // ok: path + "/sub" + '/'
2009-02-04 19:49:19 +01:00
2009-03-24 20:24:03 +01:00
TEST_CASE ( varScope1 ) ;
2009-03-24 20:59:56 +01:00
TEST_CASE ( varScope2 ) ;
2009-05-27 19:38:26 +02:00
TEST_CASE ( varScope3 ) ;
2009-06-12 16:17:51 +02:00
TEST_CASE ( varScope4 ) ;
2009-08-16 21:12:57 +02:00
TEST_CASE ( varScope5 ) ;
2009-09-17 21:05:12 +02:00
TEST_CASE ( varScope6 ) ;
2009-03-27 17:19:34 +01:00
TEST_CASE ( nullpointer1 ) ;
2009-05-10 08:43:16 +02:00
TEST_CASE ( nullpointer2 ) ;
2009-07-21 17:00:11 +02:00
TEST_CASE ( nullpointer3 ) ; // dereferencing struct and then checking if it's null
2009-07-23 14:13:46 +02:00
TEST_CASE ( nullpointer4 ) ;
2009-06-18 22:26:21 +02:00
TEST_CASE ( oldStylePointerCast ) ;
2009-07-25 00:36:15 +02:00
TEST_CASE ( postIncrementDecrementStl ) ;
TEST_CASE ( postIncrementDecrementClass ) ;
2009-10-04 10:05:58 +02:00
TEST_CASE ( dangerousStrolUsage ) ;
TEST_CASE ( passedByValue ) ;
2008-12-19 22:15:18 +01:00
}
2009-01-05 16:49:57 +01:00
void check ( const char code [ ] )
2008-12-19 22:15:18 +01:00
{
// Tokenize..
Tokenizer tokenizer ;
std : : istringstream istr ( code ) ;
2009-01-05 16:49:57 +01:00
tokenizer . tokenize ( istr , " test.cpp " ) ;
2008-12-19 22:15:18 +01:00
2009-03-28 07:49:47 +01:00
// Simplify token list..
tokenizer . simplifyTokenList ( ) ;
2008-12-19 22:15:18 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
// Check for redundant code..
2009-03-20 18:16:21 +01:00
Settings settings ;
CheckOther checkOther ( & tokenizer , & settings , this ) ;
2009-07-05 22:16:43 +02:00
checkOther . warningRedundantCode ( ) ;
checkOther . checkZeroDivision ( ) ;
2008-12-19 22:15:18 +01:00
}
2009-03-27 17:19:34 +01:00
2009-03-28 07:49:47 +01:00
void zeroDiv1 ( )
{
check ( " void foo() \n "
" { \n "
" int a = 0; \n "
" double b = 1.; \n "
" cout<<b/a; \n "
" } " ) ;
2009-05-31 21:48:55 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Division by zero \n " , errout . str ( ) ) ;
2009-03-28 07:49:47 +01:00
}
void zeroDiv2 ( )
{
check ( " void foo() \n "
" { \n "
" int sum = 0; \n "
" int n = 100; \n "
" for(int i = 0; i < n; i ++) \n "
" { \n "
" sum += i; \n "
" } \n "
" cout<<b/sum; \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-03-28 07:49:47 +01:00
2009-06-05 23:33:13 +02:00
check ( " void foo() \n "
" { \n "
" int a = 0 ? (2/0) : 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-03-28 07:49:47 +01:00
2009-08-23 05:34:19 +02:00
void zeroDiv3 ( )
{
check ( " void f() \n "
" { \n "
" div_t divresult = div (1,0); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Division by zero \n " , errout . str ( ) ) ;
}
2009-08-30 21:02:09 +02:00
void zeroDiv4 ( )
{
check ( " void f() \n "
" { \n "
" long a = b / 0x6; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" long a = b / 0x0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Division by zero \n " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" long a = b / 0L; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Division by zero \n " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" long a = b / 0ul; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Division by zero \n " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" div_t divresult = div (1,0L); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Division by zero \n " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" div_t divresult = div (1,0x5); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-09-01 16:00:26 +02:00
2009-09-01 21:06:46 +02:00
// Don't warn about floating points (gcc doesn't warn either)
// and floating points are handled differently than integers.
2009-09-01 16:00:26 +02:00
check ( " void f() \n "
" { \n "
" long a = b / 0.0; \n "
" } \n " ) ;
2009-09-01 21:06:46 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-09-01 16:00:26 +02:00
check ( " void f() \n "
" { \n "
" long a = b / 0.5; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-09-01 21:06:46 +02:00
// Don't warn about 0.0
2009-09-01 16:00:26 +02:00
check ( " void f() \n "
" { \n "
" div_t divresult = div (1,0.0); \n "
" } \n " ) ;
2009-09-01 21:06:46 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-09-01 16:00:26 +02:00
check ( " void f() \n "
" { \n "
" div_t divresult = div (1,0.5); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-08-30 21:02:09 +02:00
}
2008-12-19 22:15:18 +01:00
void delete1 ( )
{
2009-01-05 16:49:57 +01:00
check ( " void foo() \n "
" { \n "
" if (p) \n "
" { \n "
" delete p; \n "
" p = 0; \n "
" } \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-09-28 23:18:40 +02:00
check ( " void foo() \n "
" { \n "
" if (p) \n "
" delete p; \n "
" else \n "
" p = new P(); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo() \n "
" { \n "
" if (0 != g->p) \n "
" delete this->p; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo() \n "
" { \n "
" if (0 != this->g->a) \n "
" delete this->p->a; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-19 22:15:18 +01:00
}
2008-12-20 23:24:11 +01:00
void delete2 ( )
{
2009-01-05 16:49:57 +01:00
check ( " void foo() \n "
" { \n "
" if (p) \n "
" { \n "
" delete p; \n "
" } \n "
" } \n " ) ;
2009-05-31 21:48:55 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (style) Redundant condition. It is safe to deallocate a NULL pointer \n " , errout . str ( ) ) ;
2008-12-20 23:24:11 +01:00
2009-01-05 16:49:57 +01:00
check ( " void foo() \n "
" { \n "
" if (p) \n "
" delete p; \n "
" } \n " ) ;
2009-05-31 21:48:55 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (style) Redundant condition. It is safe to deallocate a NULL pointer \n " , errout . str ( ) ) ;
2009-05-19 20:23:43 +02:00
check ( " void foo() \n "
" { \n "
" if (p != NULL) \n "
" delete p; \n "
" } \n " ) ;
2009-05-31 21:48:55 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (style) Redundant condition. It is safe to deallocate a NULL pointer \n " , errout . str ( ) ) ;
2009-05-19 20:28:25 +02:00
check ( " void foo() \n "
" { \n "
" if (p) \n "
" delete [] p; \n "
" } \n " ) ;
2009-05-31 21:48:55 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (style) Redundant condition. It is safe to deallocate a NULL pointer \n " , errout . str ( ) ) ;
2009-07-18 16:42:08 +02:00
check ( " void foo() \n "
" { \n "
" if (0 != this->p) \n "
" delete this->p; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (style) Redundant condition. It is safe to deallocate a NULL pointer \n " , errout . str ( ) ) ;
2009-09-28 23:18:40 +02:00
check ( " void foo() \n "
" { \n "
" if (0 != this->p->a) \n "
" delete this->p->a; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (style) Redundant condition. It is safe to deallocate a NULL pointer \n " , errout . str ( ) ) ;
2009-07-18 16:42:08 +02:00
check ( " void Foo::deleteInstance() \n "
" { \n "
" if (Foo::instance != NULL) \n "
" delete Foo::instance; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (style) Redundant condition. It is safe to deallocate a NULL pointer \n " , errout . str ( ) ) ;
2008-12-20 23:24:11 +01:00
}
2009-01-08 22:08:14 +01:00
2009-01-18 22:19:02 +01:00
void unreachable1 ( )
{
check ( " void foo() \n "
" { \n "
" switch (p) \n "
" { \n "
" default: \n "
" return 0; \n "
" break; \n "
" } \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-01-18 22:19:02 +01:00
}
2009-01-08 22:08:14 +01:00
2009-01-08 07:24:08 +01:00
void sprintfUsage ( const char code [ ] )
{
// Tokenize..
Tokenizer tokenizer ;
std : : istringstream istr ( code ) ;
tokenizer . tokenize ( istr , " test.cpp " ) ;
tokenizer . setVarId ( ) ;
2009-01-11 11:03:21 +01:00
//tokenizer.tokens()->printOut( "tokens" );
2009-01-08 07:24:08 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
// Check for redundant code..
2009-03-20 18:16:21 +01:00
Settings settings ;
CheckOther checkOther ( & tokenizer , & settings , this ) ;
2009-07-05 22:16:43 +02:00
checkOther . invalidFunctionUsage ( ) ;
2009-01-08 07:24:08 +01:00
}
2009-01-08 22:08:14 +01:00
2009-01-08 07:24:08 +01:00
void sprintf1 ( )
{
2009-01-08 22:08:14 +01:00
sprintfUsage ( " void foo() \n "
" { \n "
" char buf[100]; \n "
" sprintf(buf, \" %s \" ,buf); \n "
" } \n " ) ;
2009-05-31 21:48:55 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Overlapping data buffer buf \n " , errout . str ( ) ) ;
2009-01-08 07:24:08 +01:00
}
2009-01-10 12:19:17 +01:00
void sprintf2 ( )
{
sprintfUsage ( " void foo() \n "
" { \n "
" char buf[100]; \n "
" sprintf(buf, \" %i \" ,sizeof(buf)); \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-01-10 12:19:17 +01:00
}
2009-01-10 15:27:31 +01:00
2009-01-10 15:29:59 +01:00
void sprintf3 ( )
{
2009-01-10 15:27:31 +01:00
sprintfUsage ( " void foo() \n "
" { \n "
" char buf[100]; \n "
" sprintf(buf, \" %i \" ,sizeof(buf)); \n "
2009-01-10 15:29:59 +01:00
" if (buf[0]); \n "
2009-01-10 15:27:31 +01:00
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-01-10 15:29:59 +01:00
}
2009-01-10 15:27:31 +01:00
2009-01-11 11:03:21 +01:00
void sprintf4 ( )
{
sprintfUsage ( " struct A \n "
" { \n "
" char filename[128]; \n "
" }; \n "
" \n "
" void foo() \n "
" { \n "
" const char* filename = \" hello \" ; \n "
" struct A a; \n "
" snprintf(a.filename, 128, \" %s \" , filename); \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-01-11 11:03:21 +01:00
}
2009-01-15 17:57:51 +01:00
void strPlusChar ( const char code [ ] )
{
// Tokenize..
Tokenizer tokenizer ;
std : : istringstream istr ( code ) ;
tokenizer . tokenize ( istr , " test.cpp " ) ;
tokenizer . setVarId ( ) ;
// Clear the error buffer..
errout . str ( " " ) ;
// Check for redundant code..
2009-03-20 18:16:21 +01:00
Settings settings ;
CheckOther checkOther ( & tokenizer , & settings , this ) ;
2009-01-15 17:57:51 +01:00
checkOther . strPlusChar ( ) ;
}
void strPlusChar1 ( )
{
// Strange looking pointer arithmetic..
strPlusChar ( " void foo() \n "
" { \n "
" const char *p = \" /usr \" + '/'; \n "
" } \n " ) ;
2009-05-31 21:48:55 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Unusual pointer arithmetic \n " , errout . str ( ) ) ;
2009-01-15 17:57:51 +01:00
}
2009-01-15 18:12:33 +01:00
void strPlusChar2 ( )
{
// Strange looking pointer arithmetic..
strPlusChar ( " void foo() \n "
" { \n "
" char ch = '/'; \n "
" const char *p = \" /usr \" + ch; \n "
" } \n " ) ;
2009-05-31 21:48:55 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Unusual pointer arithmetic \n " , errout . str ( ) ) ;
2009-01-15 18:12:33 +01:00
}
2009-01-18 18:42:41 +01:00
void strPlusChar3 ( )
{
// Strange looking pointer arithmetic..
strPlusChar ( " void foo() \n "
" { \n "
" std::string temp = \" /tmp \" ; \n "
" std::string path = temp + '/' + \" sub \" + '/'; \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-01-18 18:42:41 +01:00
}
2009-02-04 19:49:19 +01:00
2009-03-24 20:24:03 +01:00
void varScope ( const char code [ ] )
{
// Tokenize..
Tokenizer tokenizer ;
std : : istringstream istr ( code ) ;
tokenizer . tokenize ( istr , " test.cpp " ) ;
tokenizer . simplifyTokenList ( ) ;
// Clear the error buffer..
errout . str ( " " ) ;
// Check for redundant code..
Settings settings ;
settings . _checkCodingStyle = true ;
CheckOther checkOther ( & tokenizer , & settings , this ) ;
2009-07-05 22:16:43 +02:00
checkOther . checkVariableScope ( ) ;
2009-03-24 20:24:03 +01:00
}
void varScope1 ( )
{
varScope ( " unsigned short foo() \n "
" { \n "
" test_client CClient; \n "
" try \n "
" { \n "
" if (CClient.Open()) \n "
" { \n "
" return 0; \n "
" } \n "
" } \n "
" catch (...) \n "
" { \n "
" return 2; \n "
" } \n "
" \n "
" try \n "
" { \n "
" CClient.Close(); \n "
" } \n "
" catch (...) \n "
" { \n "
" return 2; \n "
" } \n "
" \n "
" return 1; \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-03-24 20:24:03 +01:00
}
2009-03-24 20:59:56 +01:00
void varScope2 ( )
{
varScope ( " int foo() \n "
" { \n "
" Error e; \n "
" e.SetValue(12); \n "
" throw e; \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-03-24 20:59:56 +01:00
}
2009-03-27 17:19:34 +01:00
2009-05-27 19:38:26 +02:00
void varScope3 ( )
{
varScope ( " void foo() \n "
" { \n "
" int i; \n "
" int *p = 0; \n "
" if (abc) \n "
" { \n "
" p = &i; \n "
" } \n "
" *p = 1; \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-05-27 19:38:26 +02:00
}
2009-06-12 16:17:51 +02:00
void varScope4 ( )
{
varScope ( " void foo() \n "
" { \n "
" int i; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-08-16 21:12:57 +02:00
void varScope5 ( )
{
2009-09-29 23:56:43 +02:00
varScope ( " void f(int x) \n "
" { \n "
" int i = 0; \n "
" if (x) { \n "
" for ( ; i < 10; ++i) ; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (style) The scope of the variable i can be limited \n " , errout . str ( ) ) ;
varScope ( " void f(int x) \n "
2009-08-16 21:12:57 +02:00
" { \n "
" int i = 0; \n "
2009-09-29 23:56:43 +02:00
" if (x) {b()} \n "
" else { \n "
2009-08-16 21:12:57 +02:00
" for ( ; i < 10; ++i) ; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (style) The scope of the variable i can be limited \n " , errout . str ( ) ) ;
}
2009-03-27 17:19:34 +01:00
2009-09-17 21:05:12 +02:00
void varScope6 ( )
{
varScope ( " void f(int x) \n "
" { \n "
" int i = x; \n "
" if (a) { \n "
" x++; \n "
" } \n "
" if (b) { \n "
" c(i); \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-09-29 23:56:43 +02:00
varScope ( " void f() \n "
" { \n "
" int foo = 0; \n "
" std::vector<int> vec(10); \n "
" BOOST_FOREACH(int& i, vec) \n "
" { \n "
" foo += 1; \n "
" if(foo == 10) \n "
" { \n "
" return 0; \n "
" } \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-03-27 17:19:34 +01:00
2009-09-29 23:56:43 +02:00
varScope ( " void f(int &x) \n "
" { \n "
" int n = 1; \n "
" do \n "
" { \n "
" ++n; \n "
" ++x; \n "
" } while (x); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-03-27 17:19:34 +01:00
void checkNullPointer ( const char code [ ] )
{
// Tokenize..
Tokenizer tokenizer ;
std : : istringstream istr ( code ) ;
tokenizer . tokenize ( istr , " test.cpp " ) ;
// Clear the error buffer..
errout . str ( " " ) ;
// Check for redundant code..
Settings settings ;
settings . _checkCodingStyle = true ;
CheckOther checkOther ( & tokenizer , & settings , this ) ;
checkOther . nullPointer ( ) ;
}
void nullpointer1 ( )
{
checkNullPointer ( " int foo(const Token *tok) \n "
" { \n "
" while (tok); \n "
" tok = tok->next(); \n "
" } \n " ) ;
2009-08-11 17:18:01 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Possible null pointer dereference: tok \n " , errout . str ( ) ) ;
2009-07-30 21:57:23 +02:00
checkNullPointer ( " void foo() \n "
" { \n "
" for (const Token *tok = tokens; tok; tok = tok->next()) \n "
" { \n "
" while (tok && tok->str() != \" ; \" ) \n "
" tok = tok->next(); \n "
" } \n "
" } \n " ) ;
2009-08-11 17:18:01 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Possible null pointer dereference: tok \n " , errout . str ( ) ) ;
2009-08-01 11:30:37 +02:00
checkNullPointer ( " void foo() \n "
" { \n "
" for (const Token *tok = tokens; tok; tok = tok ? tok->next() : NULL) \n "
" { \n "
" while (tok && tok->str() != \" ; \" ) \n "
" tok = tok->next(); \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-10-05 13:46:38 +02:00
checkNullPointer ( " void foo(A*a) \n "
" { \n "
" switch (a->b()) { \n "
" case 1: \n "
" while( a ){ \n "
" a = a->next; \n "
" } \n "
" break; \n "
" case 2: \n "
" a->b(); \n "
" break; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-03-27 17:19:34 +01:00
}
2009-05-10 08:43:16 +02:00
void nullpointer2 ( )
{
// Null pointer dereference can only happen with pointers
checkNullPointer ( " void foo() \n "
" { \n "
" Fred fred; \n "
" while (fred); \n "
" fred.hello(); \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-05-10 08:43:16 +02:00
}
2009-06-18 22:26:21 +02:00
2009-07-21 17:00:11 +02:00
// Dereferencing a struct and then checking if it is null
void nullpointer3 ( )
2009-07-20 19:30:33 +02:00
{
2009-07-21 12:09:58 +02:00
// errors..
2009-07-21 17:00:11 +02:00
checkNullPointer ( " void foo(struct ABC *abc) \n "
2009-07-22 18:48:42 +02:00
" { \n "
" int *a = abc->a; \n "
" if (!abc) \n "
" ; \n "
" } \n " ) ;
2009-08-21 12:42:40 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Possible null pointer dereference: abc - otherwise it is redundant to check if abc is null at line 4 \n " , errout . str ( ) ) ;
2009-07-21 12:09:58 +02:00
2009-08-28 08:48:37 +02:00
checkNullPointer ( " void foo(struct ABC *abc) \n "
" { \n "
" bar(abc->a); \n "
" if (!abc) \n "
" ; \n "
" } \n " ) ;
TODO_ASSERT_EQUALS ( " [test.cpp:3]: (error) Possible null pointer dereference: abc - otherwise it is redundant to check if abc is null at line 4 \n " , errout . str ( ) ) ;
2009-07-20 19:30:33 +02:00
// ok dereferencing in a condition
2009-07-21 17:00:11 +02:00
checkNullPointer ( " void foo(struct ABC *abc) \n "
2009-07-22 18:48:42 +02:00
" { \n "
" if (abc && abc->a); \n "
" if (!abc) \n "
" ; \n "
" } \n " ) ;
2009-07-20 19:30:33 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// ok to use a linked list..
2009-07-21 17:00:11 +02:00
checkNullPointer ( " void foo(struct ABC *abc) \n "
2009-07-22 18:48:42 +02:00
" { \n "
" abc = abc->next; \n "
" if (!abc) \n "
" ; \n "
" } \n " ) ;
2009-07-20 19:30:33 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-07-20 19:59:55 +02:00
// reassign struct..
2009-07-21 17:00:11 +02:00
checkNullPointer ( " void foo(struct ABC *abc) \n "
2009-07-22 18:48:42 +02:00
" { \n "
" a = abc->a; \n "
" abc = abc->next; \n "
" if (!abc) \n "
" ; \n "
" } \n " ) ;
2009-07-21 12:09:58 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-07-21 17:00:11 +02:00
checkNullPointer ( " void foo(struct ABC *abc) \n "
2009-07-22 18:48:42 +02:00
" { \n "
" a = abc->a; \n "
" f(&abc); \n "
" if (!abc) \n "
" ; \n "
" } \n " ) ;
2009-07-21 12:09:58 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// goto..
2009-07-21 17:00:11 +02:00
checkNullPointer ( " void foo(struct ABC *abc) \n "
2009-07-22 18:48:42 +02:00
" { \n "
" if (!abc) \n "
" goto out; "
" a = abc->a; \n "
" return; \n "
" out: \n "
" if (!abc) \n "
" ; \n "
" } \n " ) ;
2009-07-20 19:59:55 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-07-23 19:59:29 +02:00
2009-07-29 11:17:22 +02:00
// loops..
2009-07-23 19:59:29 +02:00
checkNullPointer ( " void freeAbc(struct ABC *abc) \n "
" { \n "
" while (abc) \n "
" { \n "
" struct ABC *next = abc->next; \n "
" if (abc) delete abc; \n "
" abc = next; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-07-29 11:17:22 +02:00
checkNullPointer ( " void foo(struct ABC *abc) \n "
" { \n "
" int a = abc->a; "
" do \n "
" { \n "
" if (abc) \n "
" abc = abc->next; \n "
" --a; \n "
" } \n "
2009-08-11 21:06:41 +02:00
" while (a > 0); \n "
2009-07-29 11:17:22 +02:00
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-09-19 10:54:10 +02:00
// dynamic_cast..
checkNullPointer ( " void foo(ABC *abc) \n "
" { \n "
" int a = abc->a; \n "
" if (!dynamic_cast<DEF *>(abc)) \n "
" ; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-07-20 19:30:33 +02:00
}
2009-07-23 14:13:46 +02:00
// Dereferencing a pointer and then checking if it is null
void nullpointer4 ( )
{
// errors..
checkNullPointer ( " void foo(int *p) \n "
" { \n "
" *p = 0; \n "
" if (!p) \n "
" ; \n "
" } \n " ) ;
2009-08-11 17:18:01 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Possible null pointer dereference: p \n " , errout . str ( ) ) ;
2009-07-23 14:13:46 +02:00
2009-08-28 08:48:37 +02:00
checkNullPointer ( " void foo(int *p) \n "
" { \n "
" bar(*p); \n "
" if (!p) \n "
" ; \n "
" } \n " ) ;
TODO_ASSERT_EQUALS ( " [test.cpp:3]: (error) Possible null pointer dereference: p \n " , errout . str ( ) ) ;
2009-07-23 14:13:46 +02:00
// no error
2009-07-23 19:02:14 +02:00
checkNullPointer ( " void foo() \n "
" { \n "
" int *p; \n "
" f(&p); \n "
" if (!p) \n "
" ; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
checkNullPointer ( " void foo() \n "
" { \n "
" int **p = f(); \n "
" if (!p) \n "
" ; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-07-23 14:13:46 +02:00
checkNullPointer ( " void foo(int *p) \n "
" { \n "
" if (x) \n "
" p = 0; \n "
" else \n "
" *p = 0; \n "
" if (!p) \n "
" ; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-07-25 20:36:02 +02:00
checkNullPointer ( " void foo(int x) \n "
" { \n "
" int a = 2 * x; "
" if (x == 0) \n "
" ; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-08-28 08:48:37 +02:00
checkNullPointer ( " void foo(int *p) \n "
" { \n "
" int var1 = p ? *p : 0; \n "
" if (!p) \n "
" ; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-09-29 15:38:05 +02:00
checkNullPointer ( " void foo(P *p) \n "
" { \n "
" while (p) \n "
" if (p->check()) \n "
" break; \n "
" else \n "
" p = p->next(); \n "
" } \n " ) ;
2009-09-30 20:42:14 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-07-23 14:13:46 +02:00
}
2009-06-18 22:26:21 +02:00
void checkOldStylePointerCast ( const char code [ ] )
{
// Tokenize..
Tokenizer tokenizer ;
std : : istringstream istr ( code ) ;
tokenizer . tokenize ( istr , " test.cpp " ) ;
tokenizer . setVarId ( ) ;
// Clear the error buffer..
errout . str ( " " ) ;
// Check for redundant code..
Settings settings ;
settings . _checkCodingStyle = true ;
CheckOther checkOther ( & tokenizer , & settings , this ) ;
2009-07-05 22:16:43 +02:00
checkOther . warningOldStylePointerCast ( ) ;
2009-06-18 22:26:21 +02:00
}
void oldStylePointerCast ( )
{
2009-06-19 12:01:27 +02:00
checkOldStylePointerCast ( " class Base; \n "
" void foo() \n "
" { \n "
" Base * b = (Base *) derived; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (style) C-style pointer casting \n " , errout . str ( ) ) ;
2009-07-20 21:52:27 +02:00
checkOldStylePointerCast ( " class Base; \n "
" void foo() \n "
" { \n "
" Base * b = (const Base *) derived; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (style) C-style pointer casting \n " , errout . str ( ) ) ;
2009-06-19 12:01:27 +02:00
2009-09-24 22:46:08 +02:00
checkOldStylePointerCast ( " class Base; \n "
" void foo() \n "
" { \n "
" Base * b = (const Base *) ( new Derived() ); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (style) C-style pointer casting \n " , errout . str ( ) ) ;
checkOldStylePointerCast ( " class Base; \n "
" void foo() \n "
" { \n "
" Base * b = (const Base *) new Derived(); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (style) C-style pointer casting \n " , errout . str ( ) ) ;
checkOldStylePointerCast ( " class Base; \n "
" void foo() \n "
" { \n "
" Base * b = (const Base *) new short[10]; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (style) C-style pointer casting \n " , errout . str ( ) ) ;
2009-06-18 22:26:21 +02:00
checkOldStylePointerCast ( " class B; \n "
" class A \n "
" { \n "
" virtual void abc(B *) const = 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-07-20 21:52:27 +02:00
checkOldStylePointerCast ( " class B; \n "
" class A \n "
" { \n "
" virtual void abc(const B *) const = 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-06-18 22:26:21 +02:00
}
2009-07-25 00:36:15 +02:00
void checkpostIncrementDecrement ( const char code [ ] )
{
// Tokenize..
Tokenizer tokenizer ;
std : : istringstream istr ( code ) ;
tokenizer . tokenize ( istr , " test.cpp " ) ;
tokenizer . setVarId ( ) ;
// Clear the error buffer..
errout . str ( " " ) ;
// Check for redundant code..
Settings settings ;
settings . _checkCodingStyle = true ;
CheckOther checkOther ( & tokenizer , & settings , this ) ;
checkOther . postIncrement ( ) ;
}
void postIncrementDecrementStl ( )
{
2009-07-25 01:23:30 +02:00
checkpostIncrementDecrement ( " void f1() \n "
" { \n "
" std::list<int>::iterator it; \n "
" for (it = ab.begin(); it != ab.end(); it++) \n "
" ; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (possible style) Pre-Incrementing variable 'it' is preferred to Post-Incrementing \n " , errout . str ( ) ) ;
checkpostIncrementDecrement ( " void f2() \n "
" { \n "
" std::list<int>::iterator it; \n "
" for (it = ab.end(); it != ab.begin(); it--) \n "
" ; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (possible style) Pre-Decrementing variable 'it' is preferred to Post-Decrementing \n " , errout . str ( ) ) ;
2009-07-25 00:36:15 +02:00
}
2009-07-25 01:23:30 +02:00
void postIncrementDecrementClass ( )
{
checkpostIncrementDecrement ( " class TestClass; \n "
" void f1() \n "
" { \n "
" TestClass tClass; \n "
" for (tClass = TestClass.begin(); tClass != TestClass.end(); tClass++) \n "
" ; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (possible style) Pre-Incrementing variable 'tClass' is preferred to Post-Incrementing \n " , errout . str ( ) ) ;
checkpostIncrementDecrement ( " class TestClass; \n "
" void f1() \n "
" { \n "
" TestClass tClass; \n "
" for (tClass = TestClass.end(); tClass != TestClass.begin(); tClass--) \n "
" ; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (possible style) Pre-Decrementing variable 'tClass' is preferred to Post-Decrementing \n " , errout . str ( ) ) ;
}
2009-07-25 00:36:15 +02:00
2009-10-04 10:05:58 +02:00
void dangerousStrolUsage ( )
{
{
sprintfUsage ( " int f(const char *num) \n "
" { \n "
" return strtol(num, NULL, 1); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Invalid radix in call to strtol or strtoul. Must be 0 or 2-36 \n " , errout . str ( ) ) ;
}
{
sprintfUsage ( " int f(const char *num) \n "
" { \n "
" return strtol(num, NULL, 10); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
}
void testPassedByValue ( const char code [ ] )
{
Tokenizer tokenizer ;
std : : istringstream istr ( code ) ;
tokenizer . tokenize ( istr , " test.cpp " ) ;
// Clear the error buffer..
errout . str ( " " ) ;
Settings settings ;
CheckOther checkOther ( & tokenizer , & settings , this ) ;
checkOther . checkConstantFunctionParameter ( ) ;
}
void passedByValue ( )
{
{
testPassedByValue ( " void f(const std::string str) \n "
" { \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:1]: (style) Function parameter 'str' is passed by value. It could be passed by reference instead. \n " , errout . str ( ) ) ;
}
{
testPassedByValue ( " class Foo; \n "
" void f(const Foo foo) \n "
" { \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (style) Function parameter 'foo' is passed by value. It could be passed by reference instead. \n " , errout . str ( ) ) ;
}
{
testPassedByValue ( " void f(const std::string &str) \n "
" { \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-10-05 10:59:28 +02:00
{
testPassedByValue ( " void f(const std::vector<int> v) \n "
" { \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:1]: (style) Function parameter 'v' is passed by value. It could be passed by reference instead. \n " , errout . str ( ) ) ;
}
{
testPassedByValue ( " void f(const std::vector<std::string> v) \n "
" { \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:1]: (style) Function parameter 'v' is passed by value. It could be passed by reference instead. \n " , errout . str ( ) ) ;
}
{
testPassedByValue ( " void f(const std::vector<int> &v) \n "
" { \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-10-04 10:05:58 +02:00
}
2008-12-19 22:15:18 +01:00
} ;
2009-01-05 16:49:57 +01:00
REGISTER_TEST ( TestOther )
2008-12-19 22:15:18 +01:00