2008-12-18 22:28:57 +01:00
/*
2009-01-21 21:04:20 +01:00
* Cppcheck - A tool for static C / C + + code analysis
2010-04-13 21:23:17 +02:00
* Copyright ( C ) 2007 - 2010 Daniel Marjamäki and Cppcheck team .
2008-12-18 22:28:57 +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-18 22:28:57 +01:00
*/
2009-10-25 12:49:06 +01:00
# include "tokenize.h"
# include "checkbufferoverrun.h"
2008-12-18 22:28:57 +01:00
# include "testsuite.h"
# include <sstream>
2010-03-30 17:33:17 +02:00
# include <climits>
2008-12-18 22:28:57 +01:00
extern std : : ostringstream errout ;
class TestBufferOverrun : public TestFixture
{
public :
TestBufferOverrun ( ) : TestFixture ( " TestBufferOverrun " )
{ }
private :
2009-10-13 23:09:37 +02:00
void check ( const char code [ ] , bool showAll = true )
2008-12-18 22:28:57 +01:00
{
// Tokenize..
Tokenizer tokenizer ;
std : : istringstream istr ( code ) ;
2009-01-05 16:49:57 +01:00
tokenizer . tokenize ( istr , " test.cpp " ) ;
2008-12-18 22:28:57 +01:00
// Assign variable ids
2009-02-02 18:27:34 +01:00
tokenizer . simplifyTokenList ( ) ;
2008-12-18 22:28:57 +01:00
// Fill function list
tokenizer . fillFunctionList ( ) ;
// Clear the error buffer..
errout . str ( " " ) ;
// Check for buffer overruns..
2010-04-17 09:23:54 +02:00
Settings settings ;
settings . inconclusive = showAll ;
2009-12-18 17:26:15 +01:00
settings . _checkCodingStyle = true ;
2009-07-13 16:00:15 +02:00
CheckBufferOverrun checkBufferOverrun ( & tokenizer , & settings , this ) ;
2008-12-20 09:53:42 +01:00
checkBufferOverrun . bufferOverrun ( ) ;
2010-04-18 20:51:39 +02:00
checkBufferOverrun . negativeIndex ( ) ;
2008-12-18 22:28:57 +01:00
}
void run ( )
{
2009-01-05 16:49:57 +01:00
TEST_CASE ( noerr1 ) ;
TEST_CASE ( noerr2 ) ;
TEST_CASE ( noerr3 ) ;
TEST_CASE ( noerr4 ) ;
2009-01-28 18:38:32 +01:00
2009-01-28 06:31:26 +01:00
TEST_CASE ( sizeof1 ) ;
2009-01-30 07:11:31 +01:00
TEST_CASE ( sizeof2 ) ;
2009-06-05 04:50:06 +02:00
TEST_CASE ( sizeof3 ) ;
2009-01-05 16:49:57 +01:00
2010-04-26 18:52:40 +02:00
TEST_CASE ( arrayInfo ) ;
2009-01-05 16:49:57 +01:00
TEST_CASE ( array_index_1 ) ;
TEST_CASE ( array_index_2 ) ;
TEST_CASE ( array_index_3 ) ;
TEST_CASE ( array_index_4 ) ;
TEST_CASE ( array_index_5 ) ;
TEST_CASE ( array_index_6 ) ;
TEST_CASE ( array_index_7 ) ;
TEST_CASE ( array_index_8 ) ;
TEST_CASE ( array_index_9 ) ;
TEST_CASE ( array_index_10 ) ;
TEST_CASE ( array_index_11 ) ;
TEST_CASE ( array_index_12 ) ;
2009-06-29 23:42:46 +02:00
TEST_CASE ( array_index_13 ) ;
2009-08-02 09:55:42 +02:00
TEST_CASE ( array_index_14 ) ;
TEST_CASE ( array_index_15 ) ;
TEST_CASE ( array_index_16 ) ;
TEST_CASE ( array_index_17 ) ;
2009-10-01 10:33:53 +02:00
TEST_CASE ( array_index_18 ) ;
2009-10-06 13:50:27 +02:00
TEST_CASE ( array_index_19 ) ;
2009-10-29 15:04:23 +01:00
TEST_CASE ( array_index_20 ) ;
2009-11-12 22:24:44 +01:00
TEST_CASE ( array_index_21 ) ;
2009-11-12 22:31:13 +01:00
TEST_CASE ( array_index_22 ) ;
2010-03-27 07:21:08 +01:00
TEST_CASE ( array_index_23 ) ;
2010-03-30 17:33:17 +02:00
TEST_CASE ( array_index_24 ) ; // ticket #1492 and #1539
2010-03-29 17:25:38 +02:00
TEST_CASE ( array_index_25 ) ; // ticket #1536
2010-04-11 22:22:16 +02:00
TEST_CASE ( array_index_26 ) ;
2010-04-25 07:34:50 +02:00
TEST_CASE ( array_index_27 ) ;
2009-10-28 21:42:54 +01:00
TEST_CASE ( array_index_multidim ) ;
2009-11-25 21:40:51 +01:00
TEST_CASE ( array_index_switch_in_for ) ;
2010-01-03 15:49:17 +01:00
TEST_CASE ( array_index_calculation ) ;
2010-01-11 21:18:07 +01:00
TEST_CASE ( array_index_negative ) ;
2010-01-31 21:02:26 +01:00
TEST_CASE ( array_index_for_decr ) ;
2010-04-08 19:57:38 +02:00
TEST_CASE ( array_index_varnames ) ; // FP: struct member. #1576
2009-01-05 16:49:57 +01:00
TEST_CASE ( buffer_overrun_1 ) ;
TEST_CASE ( buffer_overrun_2 ) ;
2009-02-11 17:12:29 +01:00
TEST_CASE ( buffer_overrun_3 ) ;
2009-06-01 19:21:08 +02:00
TEST_CASE ( buffer_overrun_4 ) ;
2009-08-26 19:17:32 +02:00
TEST_CASE ( buffer_overrun_5 ) ;
2009-08-30 13:44:23 +02:00
TEST_CASE ( buffer_overrun_6 ) ;
2009-09-26 17:58:14 +02:00
TEST_CASE ( buffer_overrun_7 ) ;
2009-09-27 16:09:41 +02:00
TEST_CASE ( buffer_overrun_8 ) ;
2009-09-27 17:07:54 +02:00
TEST_CASE ( buffer_overrun_9 ) ;
2009-09-27 17:50:59 +02:00
TEST_CASE ( buffer_overrun_10 ) ;
2009-10-05 22:19:44 +02:00
TEST_CASE ( buffer_overrun_11 ) ;
2009-11-15 13:02:03 +01:00
TEST_CASE ( buffer_overrun_12 ) ;
2010-04-24 21:48:58 +02:00
TEST_CASE ( buffer_overrun_13 ) ;
2009-01-05 16:49:57 +01:00
2009-01-14 07:29:35 +01:00
TEST_CASE ( sprintf1 ) ;
2009-08-08 16:03:10 +02:00
TEST_CASE ( sprintf2 ) ;
2009-08-08 16:52:35 +02:00
TEST_CASE ( sprintf3 ) ;
2009-09-20 12:54:19 +02:00
TEST_CASE ( sprintf4 ) ;
2009-09-26 19:06:54 +02:00
TEST_CASE ( sprintf5 ) ;
2009-09-26 19:40:58 +02:00
TEST_CASE ( sprintf6 ) ;
2009-08-08 16:03:10 +02:00
2009-01-17 14:09:02 +01:00
TEST_CASE ( snprintf1 ) ;
2009-01-24 19:55:07 +01:00
TEST_CASE ( snprintf2 ) ;
TEST_CASE ( snprintf3 ) ;
2009-03-24 18:43:39 +01:00
TEST_CASE ( snprintf4 ) ;
2009-02-20 22:16:07 +01:00
TEST_CASE ( strncat1 ) ;
2009-02-20 22:00:59 +01:00
TEST_CASE ( strncat2 ) ;
2009-01-14 07:29:35 +01:00
2010-04-05 20:02:28 +02:00
TEST_CASE ( memfunc ) ; // memchr/memset/memcpy
2009-02-21 13:22:04 +01:00
TEST_CASE ( cin1 ) ;
2009-01-05 16:49:57 +01:00
TEST_CASE ( varid1 ) ;
TEST_CASE ( varid2 ) ;
2009-02-12 20:11:52 +01:00
TEST_CASE ( assign1 ) ;
2009-03-16 18:11:09 +01:00
2010-04-10 07:57:29 +02:00
TEST_CASE ( alloc1 ) ; // Buffer allocated with new
TEST_CASE ( alloc2 ) ; // Buffer allocated with malloc
2009-03-25 07:25:10 +01:00
TEST_CASE ( memset1 ) ;
2009-11-28 12:51:23 +01:00
TEST_CASE ( memset2 ) ;
2009-09-25 18:23:44 +02:00
TEST_CASE ( counter_test ) ;
2009-09-25 22:32:18 +02:00
TEST_CASE ( strncpy1 ) ;
2009-11-15 16:44:30 +01:00
TEST_CASE ( unknownType ) ;
2009-12-18 17:26:15 +01:00
TEST_CASE ( terminateStrncpy1 ) ;
TEST_CASE ( terminateStrncpy2 ) ;
2010-02-27 22:47:56 +01:00
TEST_CASE ( recursive_long_time ) ;
2010-04-10 21:12:00 +02:00
2010-04-11 20:57:30 +02:00
TEST_CASE ( crash ) ; // Ticket #1587 - crash
2010-04-10 21:12:00 +02:00
TEST_CASE ( executionPaths1 ) ;
2008-12-18 22:28:57 +01:00
}
void noerr1 ( )
{
2009-11-07 18:03:33 +01:00
check ( " extern int ab; \n "
" void f() \n "
2009-01-05 16:49:57 +01:00
" { \n "
" if (ab) \n "
" { \n "
" char str[50]; \n "
" } \n "
" if (ab) \n "
" { \n "
" char str[50]; \n "
" } \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void noerr2 ( )
{
2009-11-07 18:03:33 +01:00
check ( " static char buf[2]; \n "
" void f1(char *str) \n "
2009-01-05 16:49:57 +01:00
" { \n "
" strcpy(buf,str); \n "
" } \n "
" void f2(char *str) \n "
" { \n "
" strcat(buf,str); \n "
" } \n "
" void f3(char *str) \n "
" { \n "
" sprintf(buf, \" %s \" ,str); \n "
" } \n "
" void f4(const char str[]) \n "
" { \n "
" strcpy(buf, str); \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void noerr3 ( )
{
2009-11-07 18:03:33 +01:00
check ( " struct { char data[10]; } abc; \n "
2009-11-09 20:34:36 +01:00
" static char f() \n "
2009-01-05 16:49:57 +01:00
" { \n "
" char data[1]; \n "
" return abc.data[1]; \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void noerr4 ( )
{
// The memory isn't read or written and therefore there is no error.
2009-01-05 16:49:57 +01:00
check ( " static void f() \n "
" { \n "
" char data[100]; \n "
" const char *p = &data[100]; \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2009-01-28 06:31:26 +01:00
void sizeof1 ( )
{
check ( " static void f() \n "
" { \n "
" char data[10]; \n "
" data[ sizeof(*data) ] = 0; \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-01-28 06:31:26 +01:00
}
2009-01-30 07:11:31 +01:00
void sizeof2 ( )
{
check ( " static void f() \n "
" { \n "
" char data[10]; \n "
" data[ sizeof(data[0]) ] = 0; \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-01-30 07:11:31 +01:00
check ( " static void f() \n "
" { \n "
" int data[2]; \n "
" data[ sizeof(data[0]) ] = 0; \n "
" } \n " ) ;
2009-12-25 15:25:58 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'data[2]' index 4 out of bounds \n " , errout . str ( ) ) ;
2009-01-30 07:11:31 +01:00
}
2009-06-05 04:50:06 +02:00
void sizeof3 ( )
{
2009-11-07 18:03:33 +01:00
check ( " struct group { int gr_gid; }; \n "
" void f() \n "
2009-06-05 04:50:06 +02:00
" { \n "
" char group[32]; \n "
" snprintf(group, sizeof(group), \" %u \" , 0); \n "
" struct group *gr; \n "
" snprintf(group, sizeof(group), \" %u \" , gr->gr_gid); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-01-28 06:31:26 +01:00
2010-04-26 18:52:40 +02:00
void arrayInfo ( )
{
// Tokenize..
Tokenizer tokenizer ;
std : : istringstream istr ( " XY(1) const int a[2] = { 1, 2 }; " ) ;
tokenizer . tokenize ( istr , " test.cpp " ) ;
// Clear the error buffer..
errout . str ( " " ) ;
tokenizer . simplifySizeof ( ) ;
CheckBufferOverrun : : ArrayInfo ai ;
ASSERT_EQUALS ( false , ai . declare ( tokenizer . tokens ( ) - > tokAt ( 5 ) , tokenizer ) ) ;
}
2008-12-18 22:28:57 +01:00
void array_index_1 ( )
{
check ( " void f() \n "
2009-01-05 16:49:57 +01:00
" { \n "
" char str[0x10]; \n "
" str[15] = 0; \n "
" str[16] = 0; \n "
" } \n " ) ;
2009-12-25 15:25:58 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'str[16]' index 16 out of bounds \n " , errout . str ( ) ) ;
2010-02-05 22:55:10 +01:00
check ( " char f() \n "
" { \n "
" char str[16]; \n "
" return str[16]; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'str[16]' index 16 out of bounds \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void array_index_2 ( )
{
check ( " void f() \n "
2009-01-05 16:49:57 +01:00
" { \n "
" char *str = new char[0x10]; \n "
" str[15] = 0; \n "
" str[16] = 0; \n "
" } \n " ) ;
2009-12-25 15:25:58 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'str[16]' index 16 out of bounds \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void array_index_3 ( )
{
2009-04-04 20:05:48 +02:00
{
check ( " void f() \n "
" { \n "
" int val[50]; \n "
2009-11-07 18:03:33 +01:00
" int i, sum=0; \n "
2009-04-04 20:05:48 +02:00
" for (i = 0; i < 100; i++) \n "
" sum += val[i]; \n "
" } \n " ) ;
2010-04-21 18:33:21 +02:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) Buffer access out-of-bounds: val \n " , errout . str ( ) ) ;
2009-04-04 20:05:48 +02:00
}
{
check ( " void f() \n "
" { \n "
" int val[50]; \n "
2009-11-07 18:03:33 +01:00
" int i, sum=0; \n "
2009-04-04 20:05:48 +02:00
" for (i = 1; i < 100; i++) \n "
" sum += val[i]; \n "
" } \n " ) ;
2010-04-21 18:33:21 +02:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) Buffer access out-of-bounds: val \n " , errout . str ( ) ) ;
2009-04-04 20:05:48 +02:00
}
{
check ( " void f(int a) \n "
" { \n "
" int val[50]; \n "
2009-11-07 18:03:33 +01:00
" int i, sum=0; \n "
2009-04-04 20:05:48 +02:00
" for (i = a; i < 100; i++) \n "
" sum += val[i]; \n "
" } \n " ) ;
2010-04-21 18:33:21 +02:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) Buffer access out-of-bounds: val \n " , errout . str ( ) ) ;
2009-04-04 20:05:48 +02:00
}
2009-11-06 23:58:33 +01:00
{
check ( " typedef struct g g2[3]; \n "
" void foo(char *a) \n "
" { \n "
" for (int i = 0; i < 4; i++) \n "
" { \n "
" a[i]=0; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2008-12-18 22:28:57 +01:00
2010-02-15 22:20:09 +01:00
{
check ( " void foo(int argc) \n "
" { \n "
" char a[2]; \n "
" for (int i = 4; i < argc; i++) \n "
" { \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
}
2008-12-18 22:28:57 +01:00
void array_index_4 ( )
{
2009-01-05 16:49:57 +01:00
check ( " const int SIZE = 10; \n "
" void f() \n "
" { \n "
" int i[SIZE]; \n "
" i[SIZE] = 0; \n "
" } \n " ) ;
2009-12-25 15:25:58 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'i[10]' index 10 out of bounds \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void array_index_5 ( )
{
2009-01-05 16:49:57 +01:00
check ( " void f() \n "
" { \n "
" int i[10]; \n "
" i[ sizeof(i) - 1 ] = 0; \n "
" } \n " ) ;
2009-12-25 15:25:58 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'i[10]' index 39 out of bounds \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void array_index_6 ( )
{
2009-01-05 16:49:57 +01:00
check ( " struct ABC \n "
" { \n "
" char str[10]; \n "
" }; \n "
" \n "
" static void f() \n "
" { \n "
" struct ABC abc; \n "
" abc.str[10] = 0; \n "
" } \n " ) ;
2009-12-25 15:25:58 +01:00
ASSERT_EQUALS ( " [test.cpp:9]: (error) Array 'str[10]' index 10 out of bounds \n " , errout . str ( ) ) ;
2009-10-13 21:39:51 +02:00
// This is not out of bounds
check ( " struct ABC \n "
" { \n "
" char str[1]; \n "
" }; \n "
" \n "
" static void f() \n "
" { \n "
2010-04-10 18:50:28 +02:00
" struct ABC* x = (struct ABC *)malloc(sizeof(struct ABC) + 10); \n "
" x->str[1] = 0; "
2009-10-13 21:39:51 +02:00
" } \n " ) ;
2010-04-10 18:50:28 +02:00
ASSERT_EQUALS ( " [test.cpp:9]: (possible error) Array 'str[1]' index 1 out of bounds \n " , errout . str ( ) ) ;
2009-10-13 21:39:51 +02:00
TODO_ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-04-22 19:22:23 +02:00
check ( " struct foo \n "
" { \n "
" char str[10]; \n "
" }; \n "
" \n "
" void x() \n "
" { \n "
" foo f; \n "
" for ( unsigned int i = 0; i < 64; ++i ) \n "
" f.str[i] = 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:10]: (error) Buffer access out-of-bounds: f.str \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void array_index_7 ( )
{
2009-01-05 16:49:57 +01:00
check ( " struct ABC \n "
" { \n "
" char str[10]; \n "
" }; \n "
" \n "
2009-11-07 18:03:33 +01:00
" static void f(struct ABC *abc) \n "
2009-01-05 16:49:57 +01:00
" { \n "
" abc->str[10] = 0; \n "
" } \n " ) ;
2009-12-25 15:25:58 +01:00
ASSERT_EQUALS ( " [test.cpp:8]: (error) Array 'str[10]' index 10 out of bounds \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void array_index_8 ( )
{
2009-01-05 16:49:57 +01:00
check ( " const int SIZE = 10; \n "
" \n "
" struct ABC \n "
" { \n "
" char str[SIZE]; \n "
" }; \n "
" \n "
" static void f() \n "
" { \n "
" struct ABC abc; \n "
" abc.str[SIZE] = 0; \n "
" } \n " ) ;
2009-12-25 15:25:58 +01:00
ASSERT_EQUALS ( " [test.cpp:11]: (error) Array 'str[10]' index 10 out of bounds \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void array_index_9 ( )
{
2009-01-05 16:49:57 +01:00
check ( " static void memclr( char *data ) \n "
" { \n "
" data[10] = 0; \n "
" } \n "
" \n "
" static void f() \n "
" { \n "
" char str[5]; \n "
" memclr( str ); // ERROR \n "
" } \n " ) ;
2010-04-21 18:33:21 +02:00
TODO_ASSERT_EQUALS ( " [test.cpp:9] -> [test.cpp:3]: (error) Array index out of bounds \n " , errout . str ( ) ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-10-13 22:33:41 +02:00
2009-12-25 15:25:58 +01:00
check ( " static void memclr( int i, char *data ) \n "
" { \n "
" data[10] = 0; \n "
" } \n "
" \n "
" static void f() \n "
" { \n "
" char str[5]; \n "
" memclr( 0, str ); // ERROR \n "
" } \n " ) ;
2010-04-21 18:33:21 +02:00
TODO_ASSERT_EQUALS ( " [test.cpp:9] -> [test.cpp:3]: (error) Array index out of bounds \n " , errout . str ( ) ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-12-25 15:25:58 +01:00
check ( " static void memclr( int i, char *data ) \n "
" { \n "
" data[i] = 0; \n "
" } \n "
" \n "
" static void f() \n "
" { \n "
" char str[5]; \n "
" memclr( 10, str ); // ERROR \n "
" } \n " ) ;
TODO_ASSERT_EQUALS ( " [test.cpp:9] -> [test.cpp:3]: (possible error) Array index out of bounds \n " , errout . str ( ) ) ;
2010-04-10 18:54:12 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ; // current result
2009-12-25 15:25:58 +01:00
2009-10-13 22:33:41 +02:00
// This is not an error
check ( " static void memclr( char *data, int size ) \n "
" { \n "
" if( size > 10 ) "
" data[10] = 0; \n "
" } \n "
" \n "
" static void f() \n "
" { \n "
" char str[5]; \n "
" memclr( str, 5 ); // ERROR \n "
" } \n " ) ;
2010-04-21 18:33:21 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void array_index_10 ( )
{
2009-01-05 16:49:57 +01:00
check ( " struct ABC \n "
" { \n "
" char str[10]; \n "
" }; \n "
" \n "
" static void memclr( char *data ) \n "
" { \n "
" data[10] = 0; \n "
" } \n "
" \n "
2009-11-07 18:03:33 +01:00
" static void f(struct ABC *abc) \n "
2009-01-05 16:49:57 +01:00
" { \n "
" memclr(abc->str); \n "
" } \n " ) ;
2009-10-13 22:33:41 +02:00
ASSERT_EQUALS ( " [test.cpp:13] -> [test.cpp:8]: (possible error) Array index out of bounds \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void array_index_11 ( )
{
2009-01-05 16:49:57 +01:00
check ( " class ABC \n "
" { \n "
" public: \n "
" ABC(); \n "
" char *str[10]; \n "
2009-11-07 18:03:33 +01:00
" struct ABC *next(); "
2009-01-05 16:49:57 +01:00
" }; \n "
" \n "
" static void f() \n "
" { \n "
2009-11-07 18:03:33 +01:00
" ABC *abc1; \n "
2009-01-05 16:49:57 +01:00
" for ( ABC *abc = abc1; abc; abc = abc->next() ) \n "
" { \n "
" abc->str[10] = 0; \n "
" } \n "
" } \n " ) ;
2009-12-25 15:25:58 +01:00
ASSERT_EQUALS ( " [test.cpp:13]: (error) Array 'str[10]' index 10 out of bounds \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void array_index_12 ( )
{
2009-01-05 16:49:57 +01:00
check ( " class Fred \n "
" { \n "
" private: \n "
" char str[10]; \n "
" public: \n "
" Fred(); \n "
" }; \n "
" Fred::Fred() \n "
" { \n "
" str[10] = 0; \n "
" } \n " ) ;
2009-12-25 15:25:58 +01:00
ASSERT_EQUALS ( " [test.cpp:10]: (error) Array 'str[10]' index 10 out of bounds \n " , errout . str ( ) ) ;
2010-02-05 22:55:10 +01:00
check ( " class Fred \n "
" { \n "
" private: \n "
" char str[10]; \n "
" public: \n "
" char c(); \n "
" }; \n "
" char Fred::c() \n "
" { \n "
" return str[10]; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:10]: (error) Array 'str[10]' index 10 out of bounds \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2009-06-29 23:42:46 +02:00
void array_index_13 ( )
{
check ( " void f() \n "
" { \n "
" char buf[10]; \n "
" for (int i = 0; i < 100; i++) \n "
" { \n "
" if (i < 10) \n "
" int x = buf[i]; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-08-02 09:55:42 +02:00
}
void array_index_14 ( )
{
check ( " void f() \n "
" { \n "
" int a[10]; \n "
" for (int i = 0; i < 10; i++) \n "
" a[i+10] = i; \n "
" } \n " ) ;
2009-12-25 15:25:58 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'a[10]' index 19 out of bounds \n " , errout . str ( ) ) ;
2009-08-02 09:55:42 +02:00
}
void array_index_15 ( )
{
check ( " void f() \n "
" { \n "
" int a[10]; \n "
" for (int i = 0; i < 10; i++) \n "
" a[10+i] = i; \n "
" } \n " ) ;
2009-12-25 15:25:58 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'a[10]' index 19 out of bounds \n " , errout . str ( ) ) ;
2009-08-02 09:55:42 +02:00
}
void array_index_16 ( )
{
check ( " void f() \n "
" { \n "
" int a[10]; \n "
" for (int i = 0; i < 10; i++) \n "
" a[i+1] = i; \n "
" } \n " ) ;
2009-12-25 15:25:58 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'a[10]' index 10 out of bounds \n " , errout . str ( ) ) ;
2009-08-02 09:55:42 +02:00
}
void array_index_17 ( )
{
check ( " void f() \n "
" { \n "
" int a[10]; \n "
" for (int i = 0; i < 10; i++) \n "
" a[i*2] = i; \n "
" } \n " ) ;
2009-12-25 15:25:58 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'a[10]' index 18 out of bounds \n " , errout . str ( ) ) ;
2009-09-30 14:51:33 +02:00
check ( " void f() \n "
" { \n "
" int a[12]; \n "
" for (int i = 0; i < 12; i+=6) \n "
" a[i+5] = i; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" int a[12]; \n "
" for (int i = 0; i < 12; i+=6) \n "
" a[i+6] = i; \n "
" } \n " ) ;
2009-12-25 15:25:58 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'a[12]' index 12 out of bounds \n " , errout . str ( ) ) ;
2009-06-29 23:42:46 +02:00
}
2009-06-01 19:21:08 +02:00
2009-10-01 10:33:53 +02:00
void array_index_18 ( )
{
check ( " void f() \n "
" { \n "
" int a[5]; \n "
" for (int i = 0; i < 6; i++) \n "
" { \n "
" a[i] = i; \n "
" i+=1; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" int a[5]; \n "
" for (int i = 0; i < 6; i++) \n "
" { \n "
" a[i] = i; \n "
" i++; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" int a[5]; \n "
" for (int i = 0; i < 6; i++) \n "
" { \n "
" a[i] = i; \n "
" ++i; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" int a[5]; \n "
" for (int i = 0; i < 6; i++) \n "
" { \n "
" a[i] = i; \n "
" i=4; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" int a[6]; \n "
" for (int i = 0; i < 7; i++) \n "
" { \n "
" a[i] = i; \n "
" i+=1; \n "
" } \n "
" } \n " ) ;
2010-04-17 15:01:18 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ; // Catch changes
2009-10-13 22:33:41 +02:00
TODO_ASSERT_EQUALS ( " [test.cpp:6]: (error) Buffer overrun \n " , errout . str ( ) ) ;
2009-10-01 10:33:53 +02:00
}
2009-10-06 13:50:27 +02:00
void array_index_19 ( )
{
// "One Past the End" is legal, as long as pointer is not dereferenced.
check ( " void f() \n "
" { \n "
" char a[2]; \n "
" char *end = &(a[2]); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// Getting more than one past the end is not legal
check ( " void f() \n "
" { \n "
" char a[2]; \n "
" char *end = &(a[3]); \n "
" } \n " ) ;
2009-12-25 15:25:58 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'a[2]' index 3 out of bounds \n " , errout . str ( ) ) ;
2009-10-06 13:50:27 +02:00
}
2009-10-29 15:04:23 +01:00
void array_index_20 ( )
{
check ( " void f() \n "
" { \n "
" char a[8]; \n "
" int b[10]; \n "
" for ( int i = 0; i < 9; i++ ) \n "
" b[i] = 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-11-12 22:24:44 +01:00
void array_index_21 ( )
{
check ( " class A { \n "
" int indices[2]; \n "
" void foo(int indices[3]); \n "
" }; \n "
" \n "
" void A::foo(int indices[3]) { \n "
" for(int j=0; j<3; ++j) { \n "
" int b = indices[j]; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-11-12 22:31:13 +01:00
void array_index_22 ( )
{
check ( " #include <cstring> \n "
" int main() { \n "
" size_t indices[2]; \n "
" int b = indices[2]; \n "
" } \n " ) ;
2009-12-25 15:25:58 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'indices[2]' index 2 out of bounds \n " , errout . str ( ) ) ;
2009-11-12 22:31:13 +01:00
}
2010-03-27 07:21:08 +01:00
void array_index_23 ( )
{
check ( " void foo() \n "
" { \n "
" char c[10]; \n "
" c[1<<23]='a'; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'c[10]' index 8388608 out of bounds \n " , errout . str ( ) ) ;
}
2010-03-28 15:56:13 +02:00
void array_index_24 ( )
{
2010-03-30 17:33:17 +02:00
// ticket #1492 and #1539
2010-04-02 07:30:58 +02:00
if ( CHAR_MAX = = SCHAR_MAX ) // plain char is signed
2010-03-30 17:33:17 +02:00
{
check ( " void f(char n) { \n "
" int a[n]; \n " // n <= CHAR_MAX
" a[-1] = 0; \n " // negative index
" a[128] = 0; \n " // 128 > CHAR_MAX
" } \n " ) ;
2010-04-18 20:51:39 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'a[128]' index 128 out of bounds \n "
2010-04-20 20:44:31 +02:00
" [test.cpp:3]: (error) Array index -1 is out of bounds \n " , errout . str ( ) ) ;
2010-04-18 20:51:39 +02:00
2010-03-30 17:33:17 +02:00
}
else // plain char is unsigned
{
check ( " void f(char n) { \n "
" int a[n]; \n " // n <= CHAR_MAX
" a[-1] = 0; \n " // negative index
" a[256] = 0; \n " // 256 > CHAR_MAX
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Array 'a[256]' index -1 out of bounds \n "
" [test.cpp:4]: (error) Array 'a[256]' index 256 out of bounds \n " , errout . str ( ) ) ;
}
2010-03-28 15:56:13 +02:00
check ( " void f(signed char n) { \n "
" int a[n]; \n " // n <= SCHAR_MAX
" a[-1] = 0; \n " // negative index
2010-03-30 17:33:17 +02:00
" a[128] = 0; \n " // 128 > SCHAR_MAX
2010-03-28 15:56:13 +02:00
" } \n " ) ;
2010-04-18 20:51:39 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'a[128]' index 128 out of bounds \n "
2010-04-20 20:44:31 +02:00
" [test.cpp:3]: (error) Array index -1 is out of bounds \n " , errout . str ( ) ) ;
2010-03-28 15:56:13 +02:00
check ( " void f(unsigned char n) { \n "
2010-03-30 17:33:17 +02:00
" int a[n]; \n " // n <= UCHAR_MAX
2010-03-28 15:56:13 +02:00
" a[-1] = 0; \n " // negative index
2010-03-30 17:33:17 +02:00
" a[256] = 0; \n " // 256 > UCHAR_MAX
2010-03-28 15:56:13 +02:00
" } \n " ) ;
2010-04-18 20:51:39 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'a[256]' index 256 out of bounds \n "
2010-04-20 20:44:31 +02:00
" [test.cpp:3]: (error) Array index -1 is out of bounds \n " , errout . str ( ) ) ;
2010-03-28 15:56:13 +02:00
check ( " void f(short n) { \n "
" int a[n]; \n " // n <= SHRT_MAX
" a[-1] = 0; \n " // negative index
" a[32768] = 0; \n " // 32768 > SHRT_MAX
" } \n " ) ;
2010-04-18 20:51:39 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'a[32768]' index 32768 out of bounds \n "
2010-04-20 20:44:31 +02:00
" [test.cpp:3]: (error) Array index -1 is out of bounds \n " , errout . str ( ) ) ;
2010-03-28 15:56:13 +02:00
check ( " void f(unsigned short n) { \n "
" int a[n]; \n " // n <= USHRT_MAX
" a[-1] = 0; \n " // negative index
" a[65536] = 0; \n " // 65536 > USHRT_MAX
" } \n " ) ;
2010-04-18 20:51:39 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'a[65536]' index 65536 out of bounds \n "
2010-04-20 20:44:31 +02:00
" [test.cpp:3]: (error) Array index -1 is out of bounds \n " , errout . str ( ) ) ;
2010-03-30 17:33:17 +02:00
check ( " void f(signed short n) { \n "
" int a[n]; \n " // n <= SHRT_MAX
" a[-1] = 0; \n " // negative index
" a[32768] = 0; \n " // 32768 > SHRT_MAX
" } \n " ) ;
2010-04-18 20:51:39 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'a[32768]' index 32768 out of bounds \n "
2010-04-20 20:44:31 +02:00
" [test.cpp:3]: (error) Array index -1 is out of bounds \n " , errout . str ( ) ) ;
2010-03-30 17:33:17 +02:00
2010-04-02 07:30:58 +02:00
if ( sizeof ( int ) = = 4 )
2010-03-30 17:33:17 +02:00
{
check ( " void f(int n) { \n "
" int a[n]; \n " // n <= INT_MAX
" a[-1] = 0; \n " // negative index
" } \n " ) ;
2010-04-20 20:44:31 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Array index -1 is out of bounds \n " , errout . str ( ) ) ;
2010-03-30 17:33:17 +02:00
check ( " void f(unsigned int n) { \n "
" int a[n]; \n " // n <= UINT_MAX
" a[-1] = 0; \n " // negative index
" } \n " ) ;
2010-04-20 20:44:31 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Array index -1 is out of bounds \n " , errout . str ( ) ) ;
2010-03-30 17:33:17 +02:00
check ( " void f(signed int n) { \n "
" int a[n]; \n " // n <= INT_MAX
" a[-1] = 0; \n " // negative index
" } \n " ) ;
2010-04-20 20:44:31 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Array index -1 is out of bounds \n " , errout . str ( ) ) ;
2010-03-30 17:33:17 +02:00
}
2010-03-28 15:56:13 +02:00
}
2010-03-29 17:25:38 +02:00
void array_index_25 ( )
{
// ticket #1536
check ( " void foo() \n "
" { \n "
" long l[SOME_SIZE]; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-04-11 22:22:16 +02:00
void array_index_26 ( )
{
check ( " void f() \n "
" { \n "
" int a[3]; \n "
" for (int i = 3; 0 <= i; i--) \n "
" a[i] = i; \n "
" } \n " ) ;
2010-04-21 18:33:21 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Buffer access out-of-bounds: a \n " , errout . str ( ) ) ;
2010-04-11 22:22:16 +02:00
check ( " void f() \n "
" { \n "
" int a[4]; \n "
" for (int i = 3; 0 <= i; i--) \n "
" a[i] = i; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-04-25 07:34:50 +02:00
void array_index_27 ( )
{
check ( " void f() \n "
" { \n "
" int a[10]; \n "
" for (int i = 0; i < 10; i++) \n "
" a[i-1] = a[i]; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'a[10]' index -1 out of bounds \n " , errout . str ( ) ) ;
}
2009-10-28 21:42:54 +01:00
void array_index_multidim ( )
{
check ( " void f() \n "
" { \n "
" char a[2][2]; \n "
" a[1][1] = 'a'; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" char a[2][2][2]; \n "
" a[1][1][1] = 'a'; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" char a[2][2]; \n "
" a[2][1] = 'a'; \n "
" } \n " ) ;
2010-04-23 16:26:40 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'a[2][2]' index a[2][1] out of bounds \n " , errout . str ( ) ) ;
2009-10-28 21:42:54 +01:00
check ( " void f() \n "
" { \n "
" char a[2][2]; \n "
" a[1][2] = 'a'; \n "
" } \n " ) ;
2010-04-23 16:26:40 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'a[2][2]' index a[1][2] out of bounds \n " , errout . str ( ) ) ;
2009-10-28 21:42:54 +01:00
check ( " void f() \n "
" { \n "
" char a[2][2][2]; \n "
" a[2][1][1] = 'a'; \n "
" } \n " ) ;
2010-04-23 16:26:40 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'a[2][2][2]' index a[2][1][1] out of bounds \n " , errout . str ( ) ) ;
2009-10-28 21:42:54 +01:00
check ( " void f() \n "
" { \n "
" char a[2][2][2]; \n "
" a[1][2][1] = 'a'; \n "
" } \n " ) ;
2010-04-23 16:26:40 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'a[2][2][2]' index a[1][2][1] out of bounds \n " , errout . str ( ) ) ;
2009-10-28 21:42:54 +01:00
2010-04-23 22:04:49 +02:00
check ( " void f() \n "
" { \n "
" char a[2][2][2][2]; \n "
" a[1][2][1][1] = 'a'; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'a[2][2][2][2]' index a[1][2][1][1] out of bounds \n " , errout . str ( ) ) ;
2009-10-28 21:42:54 +01:00
check ( " void f() \n "
" { \n "
" char a[2][2][2]; \n "
" a[1][1][2] = 'a'; \n "
" } \n " ) ;
2010-04-23 16:26:40 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'a[2][2][2]' index a[1][1][2] out of bounds \n " , errout . str ( ) ) ;
2010-04-23 21:56:35 +02:00
check ( " void f() \n "
" { \n "
" char a[10][10][10]; \n "
" a[2*3][4*3][2] = 'a'; \n "
" } \n " ) ;
TODO_ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'a[10][10][10]' index a[6][12][2] out of bounds \n " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" int i=2; \n "
" int ii=10; \n "
" char a[ii][ii][ii]; \n "
" a[i*3][4*ii][ii] = 'a'; \n "
" } \n " ) ;
2010-04-23 22:04:49 +02:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) Array 'a[10][10][10]' index a[6][40][10] out of bounds \n " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" int i=2; \n "
" int ii=1; \n "
" char a[ii][ii][ii]; \n "
" a[i][i][i] = 'a'; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (error) Array 'a[1][1][1]' index a[2][2][2] out of bounds \n " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" int i=2; \n "
" int ii=i*3; \n "
" char a[ii][ii][ii]; \n "
" a[i*3][i*3][i] = 'a'; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (error) Array 'a[6][6][6]' index a[6][6][2] out of bounds \n " , errout . str ( ) ) ;
2010-04-23 21:56:35 +02:00
2009-10-28 21:42:54 +01:00
}
2009-11-25 21:40:51 +01:00
void array_index_switch_in_for ( )
{
check ( " void f() \n "
" { \n "
" int ar[10]; \n "
" for (int i = 0; i < 10; ++i) \n "
" { \n "
" switch(i) \n "
" { \n "
" case 9: \n "
" ar[i] = 0; \n "
" break; \n "
" default: \n "
" ar[i] = ar[i+1]; \n "
" break; \n "
" }; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" int ar[10]; \n "
" for (int i = 0; i < 10; ++i) \n "
" { \n "
" switch(i) \n "
" { \n "
" case 8: \n "
" ar[i] = 0; \n "
" break; \n "
" default: \n "
" ar[i] = ar[i+1]; \n "
" break; \n "
" }; \n "
" } \n "
" } \n " ) ;
2010-01-03 15:49:17 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-11-25 21:40:51 +01:00
TODO_ASSERT_EQUALS ( " [test.cpp:12]: (error) Array index out of bounds \n " , errout . str ( ) ) ;
}
2010-01-03 15:49:17 +01:00
void array_index_calculation ( )
{
// #1193 - false negative: array out of bounds in loop when there is calculation
check ( " void f() \n "
" { \n "
2010-01-03 15:52:52 +01:00
" char data[8]; \n "
" for (int i = 19; i < 36; ++i) { \n "
" data[(i-0)/2] = 0; \n "
2010-01-03 15:49:17 +01:00
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-01-03 15:52:52 +01:00
TODO_ASSERT_EQUALS ( " [test.cpp:5]: (error) Array index out of bounds \n " , errout . str ( ) ) ;
2010-01-03 15:49:17 +01:00
}
2010-01-11 21:18:07 +01:00
void array_index_negative ( )
{
// #948 - array index out of bound not detected 'a[-1] = 0'
check ( " void f() \n "
" { \n "
" char data[8]; \n "
" data[-1] = 0; \n "
" } \n " ) ;
2010-04-20 20:44:31 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array index -1 is out of bounds \n " , errout . str ( ) ) ;
2010-04-18 21:07:21 +02:00
check ( " void f() \n "
" { \n "
" char data[8][4]; \n "
" data[5][-1] = 0; \n "
" } \n " ) ;
2010-04-20 20:44:31 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array index -1 is out of bounds \n " , errout . str ( ) ) ;
2010-04-20 16:43:51 +02:00
// #1614 - negative index is ok for pointers
check ( " void foo(char *p) \n "
" { \n "
" p[-1] = 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-01-11 21:18:07 +01:00
}
2010-01-31 21:02:26 +01:00
void array_index_for_decr ( )
{
check ( " void f() \n "
" { \n "
" char data[8]; \n "
" for (int i = 10; i > 0; --i) { \n "
" data[i] = 0; \n "
" } \n "
" } \n " ) ;
2010-04-21 18:33:21 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Buffer access out-of-bounds: data \n " , errout . str ( ) ) ;
2010-04-01 21:35:36 +02:00
check ( " void f() \n "
" { \n "
" char val[5]; \n "
" for (unsigned int i = 3; i < 5; --i) { \n "
" val[i+1] = val[i]; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" char val[5]; \n "
" for (int i = 3; i < 5; --i) { \n "
" val[i+1] = val[i]; \n "
" } \n "
" } \n " ) ;
2010-04-17 15:01:18 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ; // catch changes
2010-04-01 21:35:36 +02:00
TODO_ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'val[5]' index -1 out of bounds \n " , errout . str ( ) ) ;
2010-01-31 21:02:26 +01:00
}
2010-04-08 19:57:38 +02:00
void array_index_varnames ( )
{
check ( " struct A { \n "
" char data[4]; \n "
" struct B { char data[3]; }; \n "
" B b; \n "
" }; \n "
" \n "
" void f() \n "
" { \n "
" A a; \n "
" a.data[3] = 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2008-12-18 22:28:57 +01:00
void buffer_overrun_1 ( )
{
2009-01-05 16:49:57 +01:00
check ( " void f() \n "
" { \n "
" char str[3]; \n "
" strcpy(str, \" abc \" ); \n "
" } \n " ) ;
2010-04-21 18:33:21 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer access out-of-bounds: str \n " , errout . str ( ) ) ;
2009-11-20 22:47:06 +01:00
check ( " void f(int fd) \n "
" { \n "
" char str[3]; \n "
" read(fd, str, 3); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int fd) \n "
" { \n "
" char str[3]; \n "
" read(fd, str, 4); \n "
" } \n " ) ;
2010-04-21 18:33:21 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer access out-of-bounds: str \n " , errout . str ( ) ) ;
2009-11-20 22:47:06 +01:00
2009-11-28 13:41:24 +01:00
check ( " void f(int fd) \n "
" { \n "
" char str[3]; \n "
" write(fd, str, 3); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int fd) \n "
" { \n "
" char str[3]; \n "
" write(fd, str, 4); \n "
" } \n " ) ;
2010-04-21 18:33:21 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer access out-of-bounds: str \n " , errout . str ( ) ) ;
2009-11-28 13:41:24 +01:00
2009-12-05 11:41:30 +01:00
check ( " void f() \n "
" { \n "
" long bb[2]; \n "
" write(stdin, bb, sizeof(bb)); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-11-20 22:47:06 +01:00
check ( " void f() \n "
" { \n "
" char str[3]; \n "
2009-11-21 14:45:52 +01:00
" fgets(str, 3, stdin); \n "
2009-11-20 22:47:06 +01:00
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" char str[3]; \n "
2009-11-21 14:45:52 +01:00
" fgets(str, 4, stdin); \n "
2009-11-20 22:47:06 +01:00
" } \n " ) ;
2010-04-21 18:33:21 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer access out-of-bounds: str \n " , errout . str ( ) ) ;
2009-11-28 13:41:24 +01:00
2010-04-06 13:55:03 +02:00
// fread
check ( " void f(FILE* fd) \n "
" { \n "
2010-04-06 15:56:06 +02:00
" char str[3]; \n "
" fread(str,sizeof(char),4,fd); \n "
2010-04-06 13:55:03 +02:00
" } \n " ) ;
2010-04-21 18:33:21 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer access out-of-bounds: str \n " , errout . str ( ) ) ;
2010-04-06 13:55:03 +02:00
2010-04-06 20:56:01 +02:00
// fread
check ( " void f(FILE* fd) \n "
" { \n "
" unsigned int i = 3; \n "
" char str[i]; \n "
" fread(str,sizeof(char),i+1,fd); \n "
" } \n " ) ;
2010-04-17 15:01:18 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ; // catch changes
2010-04-06 20:56:01 +02:00
TODO_ASSERT_EQUALS ( " [test.cpp:5]: (error) Buffer access out-of-bounds \n " , errout . str ( ) ) ;
2010-04-06 13:55:03 +02:00
check ( " void f(FILE* fd) \n "
" { \n "
2010-04-06 15:56:06 +02:00
" char str[3*sizeof(char)]; \n "
" fread(str,sizeof(char),3,fd); \n "
2010-04-06 13:55:03 +02:00
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// fwrite
check ( " void f(FILE* fd) \n "
" { \n "
2010-04-06 15:56:06 +02:00
" char str[3]; \n "
" fwrite(str,sizeof(char),4,fd); \n "
2010-04-06 13:55:03 +02:00
" } \n " ) ;
2010-04-21 18:33:21 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer access out-of-bounds: str \n " , errout . str ( ) ) ;
2010-04-06 13:55:03 +02:00
check ( " void f(FILE* fd) \n "
2010-04-06 20:56:01 +02:00
" { \n "
" unsigned int i = 3; \n "
" char str[i]; \n "
" fwrite(str,sizeof(char),i+1,fd); \n "
" } \n " ) ;
2010-04-17 15:01:18 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ; // catch changes
2010-04-06 20:56:01 +02:00
TODO_ASSERT_EQUALS ( " [test.cpp:5]: (error) Buffer access out-of-bounds \n " , errout . str ( ) ) ;
check ( " void f(FILE* fd) \n "
2010-04-06 13:55:03 +02:00
" { \n "
2010-04-06 15:56:06 +02:00
" char str[3*sizeof(char)]; \n "
" fwrite(str,sizeof(char),3,fd); \n "
2010-04-06 13:55:03 +02:00
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void buffer_overrun_2 ( )
{
2009-01-05 16:49:57 +01:00
check ( " struct ABC \n "
" { \n "
" char str[5]; \n "
" }; \n "
" \n "
2009-11-07 18:03:33 +01:00
" static void f(struct ABC *abc) \n "
2009-01-05 16:49:57 +01:00
" { \n "
" strcpy( abc->str, \" abcdef \" ); \n "
" } \n " ) ;
2010-02-21 15:23:50 +01:00
ASSERT_EQUALS ( " [test.cpp:8]: (error) Buffer access out-of-bounds: abc.str \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2009-02-11 17:12:29 +01:00
void buffer_overrun_3 ( )
{
check ( " int a[10]; \n "
" \n "
" void foo() \n "
" { \n "
" int i; \n "
" for (i = 0; i <= 10; ++i) \n "
" a[i] = 0; \n "
" } \n " ) ;
2010-04-21 18:33:21 +02:00
ASSERT_EQUALS ( " [test.cpp:7]: (error) Buffer access out-of-bounds: a \n " , errout . str ( ) ) ;
2009-02-11 17:12:29 +01:00
}
2009-06-01 19:21:08 +02:00
void buffer_overrun_4 ( )
{
check ( " void foo() \n "
" { \n "
" const char *p[2]; \n "
" for (int i = 0; i < 8; ++i) \n "
" p[i] = 0; \n "
" } \n " ) ;
2010-04-21 18:33:21 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Buffer access out-of-bounds: p \n " , errout . str ( ) ) ;
2009-06-02 18:56:53 +02:00
// No false positive
check ( " void foo(int x, int y) \n "
" { \n "
" const char *p[2]; \n "
2009-11-07 18:03:33 +01:00
" const char *s = y + p[1]; \n "
2009-06-02 18:56:53 +02:00
" p[1] = 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-10-13 23:09:37 +02:00
// There is no error here
check ( " void f1(char *s,int size) \n "
" { \n "
" if( size > 10 ) strcpy(s, \" abc \" ); \n "
" } \n "
" void f2() \n "
" { \n "
" char s[3]; \n "
" f1(s,3); \n "
" } \n " ) ;
2010-04-21 18:33:21 +02:00
//ASSERT_EQUALS("[test.cpp:3]: (possible error) Buffer access out-of-bounds\n", errout.str());
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-10-13 23:09:37 +02:00
check ( " void f1(char *s,int size) \n "
" { \n "
" if( size > 10 ) strcpy(s, \" abc \" ); \n "
" } \n "
" void f2() \n "
" { \n "
" char s[3]; \n "
" f1(s,3); \n "
" } \n " , false ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-06-01 19:21:08 +02:00
}
2009-02-11 17:12:29 +01:00
2009-08-26 19:17:32 +02:00
void buffer_overrun_5 ( )
{
check ( " void f() \n "
" { \n "
" char n[5]; \n "
" sprintf(n, \" d \" ); \n "
" printf( \" hello! \" ); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-02-11 17:12:29 +01:00
2009-08-30 13:44:23 +02:00
void buffer_overrun_6 ( )
{
check ( " void f() \n "
" { \n "
" char n[5]; \n "
" strcat(n, \" abc \" ); \n "
" strcat(n, \" def \" ); \n "
" } \n " ) ;
2010-04-21 18:33:21 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Buffer access out-of-bounds: n \n " , errout . str ( ) ) ;
2009-09-05 18:46:27 +02:00
check ( " void f() \n "
" { \n "
" char n[5]; \n "
" strcat(strcat(n, \" abc \" ), \" def \" ); \n "
" } \n " ) ;
2010-04-21 18:33:21 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer access out-of-bounds: n \n " , errout . str ( ) ) ;
2009-08-30 13:44:23 +02:00
}
2009-02-11 17:12:29 +01:00
2009-09-26 17:58:14 +02:00
void buffer_overrun_7 ( )
{
// ticket #731
check ( " void f() \n "
" { \n "
" char a[2]; \n "
" strcpy(a, \" a \\ 0 \" ); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-09-27 16:09:41 +02:00
void buffer_overrun_8 ( )
{
// ticket #714
check ( " void f() \n "
" { \n "
" char a[5]; \n "
" for (int i = 0; i < 20; i+= 100) \n "
" { \n "
" a[i] = 0; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" char a[5]; \n "
" for (int i = 0; i < 20; i = i + 100) \n "
" { \n "
" a[i] = 0; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" char a[5]; \n "
" for (int i = 0; i < 20; i = 100 + i) \n "
" { \n "
" a[i] = 0; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-09-27 17:07:54 +02:00
void buffer_overrun_9 ( )
{
// ticket #738
check ( " void f() \n "
" { \n "
" char a[5]; \n "
" for (int i = 0; i < 20; ) \n "
" { \n "
" a[i] = 0; \n "
" i += 100; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-09-27 17:50:59 +02:00
void buffer_overrun_10 ( )
{
// ticket #740
check ( " void f() \n "
" { \n "
" char a[4]; \n "
" for (int i = 0; i < 4; i++) \n "
" { \n "
" char b = a[i]; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-10-05 22:19:44 +02:00
void buffer_overrun_11 ( )
{
check ( " void f() \n "
" { \n "
" char a[4]; \n "
" for (float i=0; i<10.0;i+=0.1) \n "
" { \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" char a[4]; \n "
" for (float i=0; i<10.0;i=i+0.1) \n "
" { \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" char a[4]; \n "
" for (float i=0; i<10.0;i=0.1+i) \n "
" { \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-09-27 16:09:41 +02:00
2009-11-15 13:02:03 +01:00
void buffer_overrun_12 ( )
{
// ticket #900
check ( " void f() { \n "
" char *a = new char(30); \n "
" sprintf(a, \" %s \" , \" b \" ); \n "
" delete a; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Buffer access out-of-bounds \n " , errout . str ( ) ) ;
}
2010-04-24 21:48:58 +02:00
void buffer_overrun_13 ( )
{
// ticket #836
check ( " void f() { \n "
" char a[10]; \n "
" memset(a+5, 0, 10); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Buffer access out-of-bounds: a \n " , errout . str ( ) ) ;
check ( " void f() { \n "
" char a[10]; \n "
" memmove(a, a+5, 10); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Buffer access out-of-bounds: a \n " , errout . str ( ) ) ;
}
2009-01-14 07:29:35 +01:00
void sprintf1 ( )
{
check ( " void f() \n "
" { \n "
" char str[3]; \n "
" sprintf(str, \" %s \" , \" abc \" ); \n "
" } \n " ) ;
2009-10-15 19:36:48 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer access out-of-bounds \n " , errout . str ( ) ) ;
2009-07-26 14:29:46 +02:00
check ( " void f() \n "
" { \n "
" char * c = new char[10]; \n "
" sprintf(c, \" %s \" , \" /usr/LongLongLongLongUserName/bin/LongLongApplicationName \" ); \n "
" delete [] c; \n "
" } \n " ) ;
2009-10-15 19:36:48 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer access out-of-bounds \n " , errout . str ( ) ) ;
2009-01-14 07:29:35 +01:00
}
2009-08-08 16:03:10 +02:00
void sprintf2 ( )
{
2009-11-07 18:03:33 +01:00
check ( " int getnumber(); \n "
" void f() \n "
2009-08-08 16:03:10 +02:00
" { \n "
" char str[5]; \n "
" sprintf(str, \" %d: %s \" , getnumber(), \" abcde \" ); \n "
" } \n " ) ;
2009-11-07 18:03:33 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Buffer access out-of-bounds \n " , errout . str ( ) ) ;
2009-08-08 16:52:35 +02:00
}
2009-08-08 16:03:10 +02:00
2009-08-08 16:52:35 +02:00
void sprintf3 ( )
{
check ( " void f() \n "
" { \n "
" char str[3]; \n "
" sprintf(str, \" test \" ); \n "
" } \n " ) ;
2009-10-15 19:36:48 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer access out-of-bounds \n " , errout . str ( ) ) ;
2009-08-08 16:52:35 +02:00
check ( " void f() \n "
" { \n "
" char str[5]; \n "
2009-10-07 14:37:20 +02:00
" sprintf(str, \" test%s \" , \" \" ); \n "
2009-08-08 16:52:35 +02:00
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-08-08 16:03:10 +02:00
}
2009-09-20 12:54:19 +02:00
void sprintf4 ( )
{
// ticket #690
check ( " void f() \n "
" { \n "
" char a[3]; \n "
" sprintf(a, \" %02ld \" , 99); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-09-26 19:06:54 +02:00
void sprintf5 ( )
{
// ticket #729
2009-11-07 18:03:33 +01:00
check ( " void f(int condition) \n "
2009-09-26 19:06:54 +02:00
" { \n "
" char buf[3]; \n "
" sprintf(buf, \" %s \" , condition ? \" 11 \" : \" 22 \" ); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-09-26 19:40:58 +02:00
void sprintf6 ( )
{
2009-11-07 18:03:33 +01:00
check ( " void f(int condition) \n "
2009-09-26 19:40:58 +02:00
" { \n "
" char buf[3]; \n "
" sprintf(buf, \" %s \" , condition ? \" 11 \" : \" 222 \" ); \n "
" } \n " ) ;
2010-04-17 15:01:18 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ; // catch changes
2009-10-15 19:36:48 +02:00
TODO_ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer access out-of-bounds \n " , errout . str ( ) ) ;
2009-09-26 19:40:58 +02:00
}
2009-01-17 14:09:02 +01:00
void snprintf1 ( )
{
check ( " void f() \n "
" { \n "
" char str[5]; \n "
" snprintf(str, 10, \" %s \" , \" abc \" ); \n "
" } \n " ) ;
2009-05-31 21:48:55 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) snprintf size is out of bounds \n " , errout . str ( ) ) ;
2009-01-17 14:09:02 +01:00
}
2009-01-24 19:55:07 +01:00
void snprintf2 ( )
{
check ( " void f() \n "
" { \n "
" char str[5]; \n "
" snprintf(str, 5, \" %s \" , \" abc \" ); \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-01-24 19:55:07 +01:00
}
void snprintf3 ( )
{
check ( " void f() \n "
" { \n "
" char str[5]; \n "
" snprintf(str, sizeof str, \" %s \" , \" abc \" ); \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-01-24 19:55:07 +01:00
}
2009-03-24 18:43:39 +01:00
void snprintf4 ( )
{
check ( " void f(int x) \n "
" { \n "
" char str[5]; \n "
" snprintf(str, 8 - x, \" abcdefghijkl \" ); \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-03-24 18:43:39 +01:00
}
2009-01-17 14:09:02 +01:00
2009-01-14 07:29:35 +01:00
2008-12-18 22:28:57 +01:00
2009-02-20 21:00:49 +01:00
void strncat1 ( )
{
2009-11-07 18:03:33 +01:00
check ( " void f(char *a, char *b) \n "
2009-02-20 21:00:49 +01:00
" { \n "
2009-02-20 22:16:07 +01:00
" char str[16]; \n "
" strncpy(str, a, 10); \n "
" strncat(str, b, 10); \n "
2009-02-20 21:00:49 +01:00
" } \n " ) ;
2009-07-13 10:16:31 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (possible error) Dangerous usage of strncat. Tip: the 3rd parameter means maximum number of characters to append \n " , errout . str ( ) ) ;
2009-02-20 21:00:49 +01:00
}
void strncat2 ( )
{
2009-11-07 18:03:33 +01:00
check ( " void f(char *a) \n "
2009-02-20 21:00:49 +01:00
" { \n "
" char str[5]; \n "
" strncat(str, a, 5); \n "
" } \n " ) ;
2009-07-13 10:16:31 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (possible error) Dangerous usage of strncat. Tip: the 3rd parameter means maximum number of characters to append \n " , errout . str ( ) ) ;
2009-02-20 21:00:49 +01:00
}
2010-04-05 20:02:28 +02:00
// memchr/memset/memcpy/etc
void memfunc ( )
{
2010-04-05 21:50:40 +02:00
check ( " struct S { \n "
" char a[5]; \n "
" }; \n "
" void f() \n "
" { \n "
" S s; \n "
" memset(s.a, 0, 10); \n "
" } \n " ) ;
2010-04-05 22:37:30 +02:00
ASSERT_EQUALS ( " [test.cpp:7]: (error) Buffer access out-of-bounds: s.a \n " , errout . str ( ) ) ;
2010-04-05 21:50:40 +02:00
2010-04-05 20:02:28 +02:00
check ( " void f() \n "
" { \n "
" char str[5]; \n "
" memset(str, 0, 10); \n "
" } \n " ) ;
2010-04-21 18:33:21 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer access out-of-bounds: str \n " , errout . str ( ) ) ;
2010-04-05 20:02:28 +02:00
check ( " void f() \n "
" { \n "
" char a[5], b[50]; \n "
" memcpy(a, b, 10); \n "
" } \n " ) ;
2010-04-21 18:33:21 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer access out-of-bounds: a \n " , errout . str ( ) ) ;
2010-04-05 20:02:28 +02:00
check ( " void f() \n "
" { \n "
" char a[5], b[50]; \n "
" memmove(a, b, 10); \n "
" } \n " ) ;
2010-04-21 18:33:21 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer access out-of-bounds: a \n " , errout . str ( ) ) ;
2010-04-05 20:02:28 +02:00
// When this TODO assertion works, ticket #909 can probably be closed
check ( " void f() \n "
" { \n "
" char a[5], b[50]; \n "
" memchr(a, b, 10); \n "
" } \n " ) ;
TODO_ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer access out-of-bounds \n " , errout . str ( ) ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-02-21 13:22:04 +01:00
void cin1 ( )
{
2009-11-07 19:51:18 +01:00
check ( " #include <iostream> \n "
" using namespace std; \n "
" void f() \n "
2009-02-21 13:22:04 +01:00
" { \n "
" char str[10]; \n "
" cin >> str; \n "
" } \n " ) ;
2009-11-07 19:59:03 +01:00
ASSERT_EQUALS ( " [test.cpp:6]: (possible error) Dangerous usage of std::cin, possible buffer overrun \n " , errout . str ( ) ) ;
2009-02-21 13:22:04 +01:00
}
2009-02-20 21:00:49 +01:00
2008-12-18 22:28:57 +01:00
void varid1 ( )
{
2009-01-05 16:49:57 +01:00
check ( " void foo() \n "
" { \n "
" char str[10]; \n "
" if (str[0]) \n "
" { \n "
" char str[50]; \n "
" str[30] = 0; \n "
" } \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void varid2 ( )
{
2009-01-05 16:49:57 +01:00
check ( " void foo() \n "
" { \n "
" char str[10]; \n "
" if (str[0]) \n "
" { \n "
" char str[50]; \n "
" memset(str,0,50); \n "
" } \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2009-02-12 20:11:52 +01:00
void assign1 ( )
{
check ( " char str[3] = {'a', 'b', 'c'}; \n "
" \n "
" void foo() \n "
" { \n "
" str[3] = 0; \n "
" } \n " ) ;
2009-12-25 15:25:58 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'str[3]' index 3 out of bounds \n " , errout . str ( ) ) ;
2009-02-12 20:11:52 +01:00
}
2009-03-16 18:11:09 +01:00
2010-04-10 07:57:29 +02:00
void alloc1 ( )
2009-03-16 18:11:09 +01:00
{
check ( " void foo() \n "
" { \n "
" char *s = new char[10]; \n "
" s[10] = 0; \n "
" } \n " ) ;
2009-12-25 15:25:58 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 's[10]' index 10 out of bounds \n " , errout . str ( ) ) ;
2009-03-16 18:11:09 +01:00
2010-02-10 22:11:08 +01:00
check ( " void foo() \n "
" { \n "
" char * buf = new char[8]; \n "
" buf[7] = 0; \n "
" delete [] buf; \n "
" buf = new char[9]; \n "
" buf[8] = 0; \n "
" delete [] buf; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo() \n "
" { \n "
" char * buf = new char[8]; \n "
" buf[7] = 0; \n "
" delete [] buf; \n "
" buf = new char[9]; \n "
" buf[9] = 0; \n "
" delete [] buf; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:7]: (error) Array 'buf[9]' index 9 out of bounds \n " , errout . str ( ) ) ;
check ( " void f() { \n "
" int *tab4 = malloc(20 * sizeof(int)); \n "
" tab4[19] = 0; \n "
" free(tab4); \n "
" tab4 = malloc(21 * sizeof(int)); \n "
" tab4[20] = 0; \n "
" free(tab4); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" int *tab4 = malloc(20 * sizeof(int)); \n "
" tab4[19] = 0; \n "
" tab4 = realloc(tab4,21 * sizeof(int)); \n "
" tab4[20] = 0; \n "
" free(tab4); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-03-16 18:11:09 +01:00
}
2009-03-25 07:25:10 +01:00
2010-04-10 07:57:29 +02:00
// data is allocated with malloc
void alloc2 ( )
{
check ( " void foo() \n "
" { \n "
" char *s = (char *)malloc(10); \n "
" s[10] = 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 's[10]' index 10 out of bounds \n " , errout . str ( ) ) ;
// ticket #842
check ( " void f() { \n "
" int *tab4 = malloc(20 * sizeof(int)); \n "
" tab4[20] = 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Array 'tab4[20]' index 20 out of bounds \n " , errout . str ( ) ) ;
// ticket #1134
check ( " void f() { \n "
" int *x, i; \n "
" x = malloc(10 * sizeof(int)); \n "
" x[10] = 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'x[10]' index 10 out of bounds \n " , errout . str ( ) ) ;
}
2009-03-25 07:25:10 +01:00
void memset1 ( )
{
check ( " void foo() \n "
" { \n "
" char s[10]; \n "
" memset(s, 5, '*'); \n "
" } \n " ) ;
2009-07-13 10:16:31 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (possible error) The size argument is given as a char constant \n " , errout . str ( ) ) ;
2009-10-27 19:54:35 +01:00
check ( " void foo() \n "
" { \n "
" int* x[5]; \n "
" memset(x, 0, sizeof(x)); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-03-25 07:25:10 +01:00
}
2009-09-25 18:23:44 +02:00
2009-11-28 12:51:23 +01:00
void memset2 ( )
{
check ( " class X { \n "
" char* array[2]; \n "
" X(); \n "
" }; \n "
" X::X() { \n "
" memset(array, 0, sizeof(array)); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-09-25 18:23:44 +02:00
void counter_test ( )
{
2009-10-07 14:37:20 +02:00
std : : list < const Token * > unknownParameter ;
unknownParameter . push_back ( 0 ) ;
ASSERT_EQUALS ( 6 , CheckBufferOverrun : : countSprintfLength ( " Hello " , unknownParameter ) ) ;
ASSERT_EQUALS ( 2 , CheckBufferOverrun : : countSprintfLength ( " s " , unknownParameter ) ) ;
ASSERT_EQUALS ( 2 , CheckBufferOverrun : : countSprintfLength ( " i " , unknownParameter ) ) ;
ASSERT_EQUALS ( 2 , CheckBufferOverrun : : countSprintfLength ( " %d " , unknownParameter ) ) ;
ASSERT_EQUALS ( 2 , CheckBufferOverrun : : countSprintfLength ( " %1d " , unknownParameter ) ) ;
ASSERT_EQUALS ( 3 , CheckBufferOverrun : : countSprintfLength ( " %2.2d " , unknownParameter ) ) ;
ASSERT_EQUALS ( 1 , CheckBufferOverrun : : countSprintfLength ( " %s " , unknownParameter ) ) ;
2009-10-18 12:58:48 +02:00
ASSERT_EQUALS ( 2 , CheckBufferOverrun : : countSprintfLength ( " f%s " , unknownParameter ) ) ;
2009-10-11 20:36:22 +02:00
ASSERT_EQUALS ( 1 , CheckBufferOverrun : : countSprintfLength ( " %-s " , unknownParameter ) ) ;
2009-10-07 14:37:20 +02:00
ASSERT_EQUALS ( 6 , CheckBufferOverrun : : countSprintfLength ( " %-5s " , unknownParameter ) ) ;
ASSERT_EQUALS ( 2 , CheckBufferOverrun : : countSprintfLength ( " \\ \" " , unknownParameter ) ) ;
2009-10-18 12:58:48 +02:00
ASSERT_EQUALS ( 7 , CheckBufferOverrun : : countSprintfLength ( " Hello \\ 0Text " , unknownParameter ) ) ;
ASSERT_EQUALS ( 1 , CheckBufferOverrun : : countSprintfLength ( " \\ 0 " , unknownParameter ) ) ;
2009-10-07 18:21:44 +02:00
ASSERT_EQUALS ( 2 , CheckBufferOverrun : : countSprintfLength ( " %% " , unknownParameter ) ) ;
2009-10-07 20:33:44 +02:00
ASSERT_EQUALS ( 3 , CheckBufferOverrun : : countSprintfLength ( " %d%d " , unknownParameter ) ) ;
2009-10-18 12:58:48 +02:00
ASSERT_EQUALS ( 3 , CheckBufferOverrun : : countSprintfLength ( " \\ \\ a%s \\ 0a " , unknownParameter ) ) ;
ASSERT_EQUALS ( 10 , CheckBufferOverrun : : countSprintfLength ( " \\ \\ \\ \\ Hello%d \\ 0Text \\ \\ \\ \\ " , unknownParameter ) ) ;
2009-10-07 20:33:44 +02:00
ASSERT_EQUALS ( 4 , CheckBufferOverrun : : countSprintfLength ( " %%%%%d " , unknownParameter ) ) ;
2010-01-06 20:19:27 +01:00
Token strTok ( 0 ) ;
2009-10-08 15:27:46 +02:00
strTok . str ( " \" 12345 \" " ) ;
2009-10-07 14:37:20 +02:00
std : : list < const Token * > stringAsParameter ;
2009-10-08 15:27:46 +02:00
stringAsParameter . push_back ( & strTok ) ;
ASSERT_EQUALS ( 9 , CheckBufferOverrun : : countSprintfLength ( " str%s " , stringAsParameter ) ) ;
ASSERT_EQUALS ( 6 , CheckBufferOverrun : : countSprintfLength ( " %-4s " , stringAsParameter ) ) ;
2009-10-07 20:33:44 +02:00
ASSERT_EQUALS ( 6 , CheckBufferOverrun : : countSprintfLength ( " %-5s " , stringAsParameter ) ) ;
ASSERT_EQUALS ( 7 , CheckBufferOverrun : : countSprintfLength ( " %-6s " , stringAsParameter ) ) ;
2009-10-11 21:07:18 +02:00
ASSERT_EQUALS ( 5 , CheckBufferOverrun : : countSprintfLength ( " %.4s " , stringAsParameter ) ) ;
2009-10-08 16:36:00 +02:00
ASSERT_EQUALS ( 6 , CheckBufferOverrun : : countSprintfLength ( " %.5s " , stringAsParameter ) ) ;
ASSERT_EQUALS ( 6 , CheckBufferOverrun : : countSprintfLength ( " %.6s " , stringAsParameter ) ) ;
ASSERT_EQUALS ( 6 , CheckBufferOverrun : : countSprintfLength ( " %5.6s " , stringAsParameter ) ) ;
ASSERT_EQUALS ( 7 , CheckBufferOverrun : : countSprintfLength ( " %6.6s " , stringAsParameter ) ) ;
2009-10-07 14:37:20 +02:00
std : : list < const Token * > intAsParameter ;
2010-01-06 20:19:27 +01:00
Token numTok ( 0 ) ;
2009-10-08 15:27:46 +02:00
numTok . str ( " 12345 " ) ;
2009-10-19 23:48:29 +02:00
intAsParameter . push_back ( & numTok ) ;
ASSERT_EQUALS ( 6 , CheckBufferOverrun : : countSprintfLength ( " %02ld " , intAsParameter ) ) ;
2009-10-07 20:33:44 +02:00
ASSERT_EQUALS ( 9 , CheckBufferOverrun : : countSprintfLength ( " %08ld " , intAsParameter ) ) ;
2009-10-19 23:48:29 +02:00
ASSERT_EQUALS ( 6 , CheckBufferOverrun : : countSprintfLength ( " %.2d " , intAsParameter ) ) ;
2009-10-08 16:36:00 +02:00
ASSERT_EQUALS ( 9 , CheckBufferOverrun : : countSprintfLength ( " %08.2d " , intAsParameter ) ) ;
2009-10-19 23:48:29 +02:00
TODO_ASSERT_EQUALS ( 5 , CheckBufferOverrun : : countSprintfLength ( " %x " , intAsParameter ) ) ;
ASSERT_EQUALS ( 5 , CheckBufferOverrun : : countSprintfLength ( " %4x " , intAsParameter ) ) ;
ASSERT_EQUALS ( 6 , CheckBufferOverrun : : countSprintfLength ( " %5x " , intAsParameter ) ) ;
ASSERT_EQUALS ( 5 , CheckBufferOverrun : : countSprintfLength ( " %.4x " , intAsParameter ) ) ;
ASSERT_EQUALS ( 6 , CheckBufferOverrun : : countSprintfLength ( " %.5x " , intAsParameter ) ) ;
ASSERT_EQUALS ( 6 , CheckBufferOverrun : : countSprintfLength ( " %1.5x " , intAsParameter ) ) ;
ASSERT_EQUALS ( 6 , CheckBufferOverrun : : countSprintfLength ( " %5.1x " , intAsParameter ) ) ;
2009-10-08 16:36:00 +02:00
std : : list < const Token * > floatAsParameter ;
2010-01-06 20:19:27 +01:00
Token floatTok ( 0 ) ;
2009-10-08 16:36:00 +02:00
floatTok . str ( " 1.12345f " ) ;
2009-10-19 23:48:29 +02:00
floatAsParameter . push_back ( & floatTok ) ;
2009-10-08 16:36:00 +02:00
TODO_ASSERT_EQUALS ( 5 , CheckBufferOverrun : : countSprintfLength ( " %.2f " , floatAsParameter ) ) ;
ASSERT_EQUALS ( 9 , CheckBufferOverrun : : countSprintfLength ( " %8.2f " , floatAsParameter ) ) ;
TODO_ASSERT_EQUALS ( 5 , CheckBufferOverrun : : countSprintfLength ( " %2.2f " , floatAsParameter ) ) ;
std : : list < const Token * > floatAsParameter2 ;
2010-01-06 20:19:27 +01:00
Token floatTok2 ( 0 ) ;
2009-10-08 16:36:00 +02:00
floatTok2 . str ( " 100.12345f " ) ;
2009-10-19 23:48:29 +02:00
floatAsParameter2 . push_back ( & floatTok2 ) ;
2009-10-08 16:36:00 +02:00
TODO_ASSERT_EQUALS ( 7 , CheckBufferOverrun : : countSprintfLength ( " %2.2f " , floatAsParameter2 ) ) ;
TODO_ASSERT_EQUALS ( 7 , CheckBufferOverrun : : countSprintfLength ( " %.2f " , floatAsParameter ) ) ;
TODO_ASSERT_EQUALS ( 7 , CheckBufferOverrun : : countSprintfLength ( " %4.2f " , floatAsParameter ) ) ;
2009-10-07 20:33:44 +02:00
std : : list < const Token * > multipleParams ;
2009-10-08 15:27:46 +02:00
multipleParams . push_back ( & strTok ) ;
multipleParams . push_back ( 0 ) ;
multipleParams . push_back ( & numTok ) ;
2009-10-19 23:48:29 +02:00
ASSERT_EQUALS ( 15 , CheckBufferOverrun : : countSprintfLength ( " str%s%d%d " , multipleParams ) ) ;
2009-10-07 20:33:44 +02:00
ASSERT_EQUALS ( 26 , CheckBufferOverrun : : countSprintfLength ( " str%-6s%08ld%08ld " , multipleParams ) ) ;
2009-10-08 15:27:46 +02:00
2009-09-25 18:23:44 +02:00
}
2009-09-25 22:32:18 +02:00
void strncpy1 ( )
{
check ( " void f() \n "
" { \n "
2010-04-21 19:27:28 +02:00
" char a[6]; \n "
" char c[7]; \n "
" strcpy(a, \" hello \" ); \n "
" strncpy(c, a, sizeof(c)); \n "
2009-09-25 22:32:18 +02:00
" } \n " ) ;
2010-04-21 20:02:58 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-09-25 22:32:18 +02:00
check ( " void f() \n "
" { \n "
" char a[6]; \n "
" char c[6]; \n "
" strcpy(a, \" hello \" ); \n "
" strncpy(c,a,sizeof(c)); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" char a[6]; \n "
" char c[5]; \n "
" strcpy(a, \" hello \" ); \n "
" strncpy(c,a,sizeof(c)+1); \n "
" } \n " ) ;
2010-04-21 18:33:21 +02:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) Buffer access out-of-bounds: c \n " , errout . str ( ) ) ;
2009-09-25 22:32:18 +02:00
check ( " void f() \n "
" { \n "
" char c[6]; \n "
" strncpy(c, \" hello! \" ,sizeof(c)); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
2010-04-21 19:27:28 +02:00
" char c[6]; \n "
" strncpy(c, \" hello! \" ,sizeof(c)+1); \n "
2009-09-25 22:32:18 +02:00
" } \n " ) ;
2010-04-21 18:33:21 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer access out-of-bounds: c \n " , errout . str ( ) ) ;
2010-02-21 15:23:50 +01:00
check ( " struct AB { char a[10]; }; \n "
" void foo(AB *ab) \n "
" { \n "
" strncpy(x, ab->a, 100); \n "
" } \n " ) ;
2010-04-21 20:02:58 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-09-25 22:32:18 +02:00
}
2009-11-15 16:44:30 +01:00
void unknownType ( )
{
check ( " void f() \n "
" { \n "
" UnknownType *a = malloc(4); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-12-18 17:26:15 +01:00
void terminateStrncpy1 ( )
{
2009-12-19 17:57:58 +01:00
check ( " void foo ( char *bar ) \n "
" { \n "
2009-12-18 17:26:15 +01:00
" char baz[100]; \n "
" strncpy(baz, bar, sizeof(baz)); \n "
" strncpy(baz, bar, sizeof(baz)); \n "
" baz[99] = 0; \n "
" strncpy(baz, bar, sizeof(baz)); \n "
" baz[sizeof(baz)-1] = 0; \n "
" strncpy(baz, bar, sizeof(baz)); \n "
" *(baz + 99) = 0; \n "
" strncpy(baz, bar, sizeof(baz)); \n "
" bar[99] = 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (style) After a strncpy() the buffer should be zero-terminated \n " , errout . str ( ) ) ;
2010-04-05 20:47:50 +02:00
// Test with invalid code that there is no segfault
check ( " char baz[100]; \n "
" strncpy(baz, \" var \" , sizeof(baz)) \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// Test that there are no duplicate error messages
check ( " void foo ( char *bar ) \n "
" { \n "
" char baz[100]; \n "
" strncpy(baz, bar, sizeof(baz)); \n "
" foo(baz); \n "
" foo(baz); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (style) After a strncpy() the buffer should be zero-terminated \n " , errout . str ( ) ) ;
2009-12-18 17:26:15 +01:00
}
void terminateStrncpy2 ( )
{
2009-12-19 17:57:58 +01:00
check ( " char *foo ( char *bar ) \n "
" { \n "
2009-12-18 17:26:15 +01:00
" char baz[100]; \n "
" strncpy(baz, bar, sizeof(baz)); \n "
" bar[99] = 0; \n "
" return baz; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (style) After a strncpy() the buffer should be zero-terminated \n " , errout . str ( ) ) ;
}
2010-02-27 22:47:56 +01:00
void recursive_long_time ( )
{
// Just test that recursive check doesn't take long time
check ( " char *f2 ( char *b ) \n "
" { \n "
" f2( b ); \n "
" f2( b ); \n "
" f2( b ); \n "
" f2( b ); \n "
" f2( b ); \n "
" f2( b ); \n "
" f2( b ); \n "
" f2( b ); \n "
" f2( b ); \n "
" f2( b ); \n "
" f2( b ); \n "
" f2( b ); \n "
" f2( b ); \n "
" f2( b ); \n "
" f2( b ); \n "
" } \n "
" void f() \n "
" { \n "
" char a[10]; \n "
" f2(a); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-04-10 21:12:00 +02:00
2010-04-11 20:57:30 +02:00
// Ticket #1587 - crash
void crash ( )
{
check ( " struct struct A \n "
" { \n "
" int alloclen; \n "
" }; \n "
" \n "
" void foo() \n "
" { \n "
" struct A *str; \n "
" str = malloc(4); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-04-10 21:12:00 +02:00
void epcheck ( 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 buffer overruns..
Settings settings ;
CheckBufferOverrun checkBufferOverrun ( & tokenizer , & settings , this ) ;
checkBufferOverrun . executionPaths ( ) ;
}
void executionPaths1 ( )
{
epcheck ( " void f(int a) \n "
" { \n "
" int buf[10]; \n "
" int i = 5; \n "
" if (a == 1) \n "
" i = 1000; \n "
" buf[i] = 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:7]: (error) Array 'buf[10]' index 1000 out of bounds \n " , errout . str ( ) ) ;
2010-04-18 11:08:29 +02:00
epcheck ( " void f(int a) \n "
" { \n "
" int buf[10][5]; \n "
" int i = 5; \n "
" if (a == 1) \n "
" i = 1000; \n "
" buf[i][0] = 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:7]: (error) Array 'buf[10][5]' index 1000 out of bounds \n " , errout . str ( ) ) ;
2010-04-10 21:12:00 +02:00
}
2008-12-18 22:28:57 +01:00
} ;
2009-01-05 16:49:57 +01:00
REGISTER_TEST ( TestBufferOverrun )
2008-12-18 22:28:57 +01:00