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
2011-01-09 20:33:36 +01:00
* Copyright ( C ) 2007 - 2011 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 :
2011-04-10 15:55:08 +02:00
void check ( const char code [ ] , bool experimental = true )
2008-12-18 22:28:57 +01:00
{
2010-12-01 18:00:55 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
Settings settings ;
2011-08-21 20:44:55 +02:00
settings . inconclusive = true ;
2011-04-10 15:55:08 +02:00
settings . experimental = experimental ;
2011-08-07 09:28:08 +02:00
settings . addEnabled ( " style " ) ;
2011-09-03 15:30:30 +02:00
settings . addEnabled ( " portability " ) ;
2010-12-01 18:00:55 +01:00
2008-12-18 22:28:57 +01:00
// Tokenize..
2010-12-01 18:00:55 +01:00
Tokenizer tokenizer ( & settings , this ) ;
2008-12-18 22:28:57 +01:00
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 ( ) ;
// Check for buffer overruns..
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 ( ) ;
2011-08-04 11:15:14 +02:00
checkBufferOverrun . arrayIndexThenCheck ( ) ;
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_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 ) ;
2010-05-16 23:53:42 +02:00
TEST_CASE ( array_index_28 ) ; // ticket #1418
2010-06-06 16:20:50 +02:00
TEST_CASE ( array_index_29 ) ; // ticket #1734
2010-10-11 20:52:14 +02:00
TEST_CASE ( array_index_30 ) ; // ticket #2086 - out of bounds when type is unknown
2010-10-23 08:49:03 +02:00
TEST_CASE ( array_index_31 ) ; // ticket #2120 - out of bounds in subfunction when type is unknown
2011-01-31 13:46:51 +01:00
TEST_CASE ( array_index_32 ) ;
2011-08-28 17:40:55 +02:00
TEST_CASE ( array_index_33 ) ; // ticket #3044
2011-09-03 01:35:09 +02:00
TEST_CASE ( array_index_34 ) ; // ticket #3063
2011-09-05 01:54:57 +02:00
TEST_CASE ( array_index_35 ) ; // ticket #2889
2011-09-12 03:51:05 +02:00
TEST_CASE ( array_index_36 ) ; // ticket #2960
2011-09-23 03:23:40 +02:00
TEST_CASE ( array_index_37 ) ;
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 ) ;
2011-03-08 19:49:56 +01:00
TEST_CASE ( array_index_for_in_for ) ; // FP: #2634
2010-01-03 15:49:17 +01:00
TEST_CASE ( array_index_calculation ) ;
2011-09-03 03:07:29 +02:00
TEST_CASE ( array_index_negative1 ) ;
TEST_CASE ( array_index_negative2 ) ; // ticket #3063
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
2010-12-19 10:39:43 +01:00
TEST_CASE ( array_index_for_break ) ; // FP: for,break
2010-12-28 20:46:31 +01:00
TEST_CASE ( array_index_for ) ; // FN: for,if
2011-01-09 18:51:28 +01:00
TEST_CASE ( array_index_for_neq ) ; // #2211: Using != in condition
2011-02-12 11:31:10 +01:00
TEST_CASE ( array_index_for_question ) ; // #2561: for, ?:
2011-05-07 11:34:48 +02:00
TEST_CASE ( array_index_extern ) ; // FP when using 'extern'. #1684
2011-06-29 18:44:05 +02:00
TEST_CASE ( array_index_cast ) ; // FP after cast. #2841
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 ) ;
2010-05-26 10:56:34 +02:00
TEST_CASE ( buffer_overrun_14 ) ;
2010-06-13 07:17:50 +02:00
TEST_CASE ( buffer_overrun_15 ) ; // ticket #1787
2010-10-12 19:35:20 +02:00
TEST_CASE ( buffer_overrun_16 ) ;
2011-02-11 18:57:58 +01:00
TEST_CASE ( buffer_overrun_17 ) ; // ticket #2548
2011-02-12 18:34:12 +01:00
TEST_CASE ( buffer_overrun_18 ) ; // ticket #2576 - for, calculation with loop variable
2011-02-20 21:24:57 +01:00
TEST_CASE ( buffer_overrun_19 ) ; // #2597 - class member with unknown type
2011-08-10 01:45:18 +02:00
TEST_CASE ( buffer_overrun_20 ) ; // #2986 (segmentation fault)
2011-08-24 12:53:27 +02:00
TEST_CASE ( buffer_overrun_21 ) ;
2011-09-20 02:32:50 +02:00
TEST_CASE ( buffer_overrun_22 ) ; // #3124
2011-09-30 23:28:59 +02:00
TEST_CASE ( buffer_overrun_23 ) ; // #3153
2010-12-31 18:07:46 +01:00
TEST_CASE ( buffer_overrun_bailoutIfSwitch ) ; // ticket #2378 : bailoutIfSwitch
2011-08-21 20:44:55 +02:00
TEST_CASE ( possible_buffer_overrun_1 ) ; // #3035
2009-01-05 16:49:57 +01:00
2010-12-26 21:23:28 +01:00
// It is undefined behaviour to point out of bounds of an array
// the address beyond the last element is in bounds
// char a[10];
// char *p1 = a + 10; // OK
// char *p2 = a + 11 // UB
TEST_CASE ( pointer_out_of_bounds_1 ) ;
2011-01-01 20:56:21 +01:00
TEST_CASE ( pointer_out_of_bounds_2 ) ;
2010-12-26 21:23:28 +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 ) ;
2010-05-29 07:51:28 +02:00
TEST_CASE ( sprintf7 ) ;
TEST_CASE ( sprintf8 ) ;
2010-10-19 18:23:44 +02:00
TEST_CASE ( sprintf9 ) ;
2010-10-22 20:15:51 +02:00
TEST_CASE ( sprintf10 ) ;
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 ) ;
2010-05-29 07:51:28 +02:00
TEST_CASE ( snprintf5 ) ;
TEST_CASE ( snprintf6 ) ;
2010-11-18 19:26:46 +01:00
TEST_CASE ( snprintf7 ) ;
2009-02-20 22:16:07 +01:00
TEST_CASE ( strncat1 ) ;
2009-02-20 22:00:59 +01:00
TEST_CASE ( strncat2 ) ;
2010-05-29 07:51:28 +02:00
TEST_CASE ( strncat3 ) ;
2010-05-29 11:19:56 +02:00
2010-05-29 07:51:28 +02:00
TEST_CASE ( strcat1 ) ;
TEST_CASE ( strcat2 ) ;
2010-12-18 10:54:36 +01:00
TEST_CASE ( strcat3 ) ;
2009-01-14 07:29:35 +01:00
2010-10-23 13:12:17 +02:00
TEST_CASE ( memfunc1 ) ; // memchr/memset/memcpy
TEST_CASE ( memfunc2 ) ;
2010-04-05 20:02:28 +02:00
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
2010-10-10 09:15:18 +02:00
TEST_CASE ( alloc3 ) ; // statically allocated buffer
2011-07-17 09:35:51 +02:00
TEST_CASE ( alloc4 ) ; // Buffer allocated with alloca
2011-01-22 21:31:26 +01:00
TEST_CASE ( malloc_memset ) ; // using memset on 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-11-07 09:37:45 +01:00
TEST_CASE ( terminateStrncpy3 ) ;
2010-02-27 22:47:56 +01:00
TEST_CASE ( recursive_long_time ) ;
2010-04-10 21:12:00 +02:00
2011-03-09 21:00:28 +01:00
TEST_CASE ( crash1 ) ; // Ticket #1587 - crash
TEST_CASE ( crash2 ) ; // Ticket #2607 - crash
2011-08-29 19:16:52 +02:00
TEST_CASE ( crash3 ) ; // Ticket #3034 - crash
2010-04-11 20:57:30 +02:00
2010-04-10 21:12:00 +02:00
TEST_CASE ( executionPaths1 ) ;
2010-07-05 22:19:27 +02:00
TEST_CASE ( executionPaths2 ) ;
2010-10-30 12:32:43 +02:00
TEST_CASE ( executionPaths3 ) ; // no FP for function parameter
2010-12-31 20:55:28 +01:00
TEST_CASE ( executionPaths4 ) ; // Ticket #2386 - Segmentation fault in the ExecutionPath handling
2011-07-20 07:57:42 +02:00
TEST_CASE ( executionPaths5 ) ; // Ticket #2920 - False positive when size is unknown
2010-06-02 18:09:25 +02:00
2010-06-02 07:41:07 +02:00
TEST_CASE ( cmdLineArgs1 ) ;
2010-08-24 22:03:18 +02:00
TEST_CASE ( scope ) ; // handling different scopes
2010-12-16 20:15:22 +01:00
2010-12-13 18:17:33 +01:00
TEST_CASE ( getErrorMessages ) ;
2011-03-13 17:52:45 +01:00
TEST_CASE ( unknownMacroNoDecl ) ; // #2638 - not variable declaration: 'AAA a[0] = 0;'
2011-08-04 11:15:14 +02:00
// Access array and then check if the used index is within bounds
TEST_CASE ( arrayIndexThenCheck ) ;
2011-09-05 21:59:41 +02:00
TEST_CASE ( bufferNotZeroTerminated ) ;
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 ( )
{
2010-12-01 18:00:55 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
Settings settings ;
2010-04-26 18:52:40 +02:00
// Tokenize..
2010-12-01 18:00:55 +01:00
Tokenizer tokenizer ( & settings , this ) ;
2010-04-26 18:52:40 +02:00
std : : istringstream istr ( " XY(1) const int a[2] = { 1, 2 }; " ) ;
tokenizer . tokenize ( istr , " test.cpp " ) ;
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 ( ) ) ;
}
2011-08-07 17:54:25 +02:00
{
check ( " void foo(int a[10]) { \n "
" for (int i=0;i<50;++i) { \n "
" a[i] = 0; \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Buffer access out-of-bounds: a \n " , errout . str ( ) ) ;
}
2010-02-15 22:20:09 +01:00
}
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 " ) ;
2011-09-12 01:21:13 +02:00
ASSERT_EQUALS ( " [test.cpp:9]: (error) Array 'abc.str[10]' index 10 out of bounds \n " , errout . str ( ) ) ;
2009-10-13 21:39:51 +02:00
2011-09-11 20:00:53 +02:00
check ( " struct ABC \n "
" { \n "
" char str[10]; \n "
" }; \n "
" \n "
" static char f() \n "
" { \n "
" struct ABC abc; \n "
" return abc.str[10]; \n "
" } \n " ) ;
2011-09-12 01:21:13 +02:00
ASSERT_EQUALS ( " [test.cpp:9]: (error) Array 'abc.str[10]' index 10 out of bounds \n " , errout . str ( ) ) ;
2011-09-11 20:00:53 +02:00
2011-09-04 20:39:24 +02:00
// This is not out of bounds because it is a variable length array
2009-10-13 21:39:51 +02:00
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-05-16 15:30:39 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-04-22 19:22:23 +02:00
2011-09-09 13:46:06 +02:00
// This is not out of bounds because it is not a variable length array
check ( " struct ABC \n "
" { \n "
" char str[1]; \n "
" int x; \n "
" }; \n "
" \n "
" static void f() \n "
" { \n "
" struct ABC* x = (struct ABC *)malloc(sizeof(struct ABC) + 10); \n "
" x->str[1] = 0; "
" } \n " ) ;
2011-09-12 01:21:13 +02:00
ASSERT_EQUALS ( " [test.cpp:10]: (error) Array 'x.str[1]' index 1 out of bounds \n " , errout . str ( ) ) ;
2011-09-09 13:46:06 +02:00
2011-09-05 01:54:57 +02:00
// This is not out of bounds because it is a variable length array
// and the index is within the memory allocated.
/** @todo this works by accident because we ignore any access to this array */
2011-09-04 20:39:24 +02:00
check ( " struct ABC \n "
" { \n "
" char str[1]; \n "
" }; \n "
" \n "
" static void f() \n "
" { \n "
" struct ABC* x = (struct ABC *)malloc(sizeof(struct ABC) + 10); \n "
" x->str[10] = 0; "
" } \n " ) ;
2011-09-05 01:54:57 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-09-04 20:39:24 +02:00
2011-09-05 01:54:57 +02:00
// This is out of bounds because it is outside the memory allocated.
2011-09-10 16:14:32 +02:00
/** @todo this doesn't work because of a bug in sizeof(struct) */
2011-09-04 20:39:24 +02:00
check ( " struct ABC \n "
" { \n "
" char str[1]; \n "
" }; \n "
" \n "
" static void f() \n "
" { \n "
" struct ABC* x = (struct ABC *)malloc(sizeof(struct ABC) + 10); \n "
" x->str[11] = 0; "
" } \n " ) ;
2011-09-05 01:54:57 +02:00
TODO_ASSERT_EQUALS ( " [test.cpp:9]: (error) Array 'str[1]' index 11 out of bounds \n " , " " , errout . str ( ) ) ;
2011-09-04 20:39:24 +02:00
2011-09-10 16:14:32 +02:00
// This is out of bounds because it is outside the memory allocated.
check ( " struct ABC \n "
" { \n "
" char str[1]; \n "
" }; \n "
" \n "
" static void f() \n "
" { \n "
" struct ABC* x = (struct ABC *)malloc(sizeof(ABC) + 10); \n "
" x->str[11] = 0; "
" } \n " ) ;
2011-09-12 01:21:13 +02:00
ASSERT_EQUALS ( " [test.cpp:9]: (error) Array 'x.str[11]' index 11 out of bounds \n " , errout . str ( ) ) ;
2011-09-10 16:14:32 +02:00
2011-09-04 20:39:24 +02:00
// This is out of bounds because it is outside the memory allocated
2011-09-10 16:14:32 +02:00
/** @todo this doesn't work because of a bug in sizeof(struct) */
2011-09-04 20:39:24 +02:00
check ( " struct ABC \n "
" { \n "
" char str[1]; \n "
" }; \n "
" \n "
" static void f() \n "
" { \n "
" struct ABC* x = (struct ABC *)malloc(sizeof(struct ABC)); \n "
" x->str[1] = 0; "
" } \n " ) ;
TODO_ASSERT_EQUALS ( " [test.cpp:9]: (error) Array 'str[1]' index 1 out of bounds \n " , " " , errout . str ( ) ) ;
2011-09-10 16:14:32 +02:00
// This is out of bounds because it is outside the memory allocated
check ( " struct ABC \n "
" { \n "
" char str[1]; \n "
" }; \n "
" \n "
" static void f() \n "
" { \n "
" struct ABC* x = (struct ABC *)malloc(sizeof(ABC)); \n "
" x->str[1] = 0; "
" } \n " ) ;
2011-09-12 01:21:13 +02:00
ASSERT_EQUALS ( " [test.cpp:9]: (error) Array 'x.str[1]' index 1 out of bounds \n " , errout . str ( ) ) ;
2011-09-10 16:14:32 +02:00
2011-09-04 20:39:24 +02:00
// This is out of bounds because it is not a variable array
check ( " struct ABC \n "
" { \n "
" char str[1]; \n "
" }; \n "
" \n "
" static void f() \n "
" { \n "
" struct ABC x; \n "
" x.str[1] = 0; "
" } \n " ) ;
2011-09-12 01:21:13 +02:00
ASSERT_EQUALS ( " [test.cpp:9]: (error) Array 'x.str[1]' index 1 out of bounds \n " , errout . str ( ) ) ;
2011-09-04 20:39:24 +02:00
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 " ) ;
2011-09-12 01:21:13 +02:00
ASSERT_EQUALS ( " [test.cpp:8]: (error) Array 'abc.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 " ) ;
2011-09-12 01:21:13 +02:00
ASSERT_EQUALS ( " [test.cpp:11]: (error) Array 'abc.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-08-05 11:01:47 +02:00
ASSERT_EQUALS ( " [test.cpp:9] -> [test.cpp:3]: (error) Array 'str[5]' index 10 out of bounds \n " , 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-08-05 11:01:47 +02:00
ASSERT_EQUALS ( " [test.cpp:9] -> [test.cpp:3]: (error) Array 'str[5]' index 10 out of bounds \n " , 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 " ) ;
2011-01-30 12:54:19 +01:00
TODO_ASSERT_EQUALS ( " [test.cpp:9] -> [test.cpp:3]: (possible error) Array index out of bounds \n " ,
" " , errout . str ( ) ) ;
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 ( ) ) ;
2010-10-14 20:00:32 +02:00
// #2097..
check ( " void foo(int *p) \n "
" { \n "
" --p; \n "
" p[2] = 0; \n "
" } \n "
" \n "
" void bar() \n "
" { \n "
" int p[3]; \n "
" foo(p+1); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , 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 " ) ;
2011-09-12 01:21:13 +02:00
ASSERT_EQUALS ( " [test.cpp:13]: (error) Array 'abc.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 " ) ;
2011-01-30 12:54:19 +01: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
2011-02-22 20:46:12 +01:00
// CHAR_MAX can be equal to SCHAR_MAX or UCHAR_MAX depending on the environment.
// This test should work for both environments.
std : : ostringstream charMaxPlusOne ;
charMaxPlusOne < < ( CHAR_MAX + 1 ) ;
check ( ( " void f(char n) { \n "
" int a[n]; \n " // n <= CHAR_MAX
" a[-1] = 0; \n " // negative index
" a[ " + charMaxPlusOne . str ( ) + " ] = 0; \n " // 128/256 > CHAR_MAX
" } \n " ) . c_str ( ) ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'a[ " + charMaxPlusOne . str ( ) + " ]' index " + charMaxPlusOne . str ( ) + " out of bounds \n "
" [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
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 ( ) ) ;
}
2010-05-17 19:51:35 +02:00
void array_index_28 ( )
2010-05-16 23:53:42 +02:00
{
2010-05-17 19:51:35 +02:00
// ticket #1418
2010-05-16 23:53:42 +02:00
check ( " void f() \n "
" { \n "
" int i[2]; \n "
" int *ip = &i[1]; \n "
" ip[-10] = 1; \n "
" } \n " ) ;
2011-01-30 12:54:19 +01:00
TODO_ASSERT_EQUALS ( " [test.cpp:5]: (error) Array ip[-10] out of bounds \n " , " " , errout . str ( ) ) ;
2010-05-16 23:53:42 +02:00
}
2010-04-25 07:34:50 +02:00
2010-06-06 16:20:50 +02:00
void array_index_29 ( )
{
// ticket #1724
check ( " void f() \n "
" { \n "
" int iBuf[10]; "
" int *i = &iBuf[9]; "
" int *ii = &i[-5]; "
" ii[10] = 0; "
" } \n " ) ;
2011-01-30 12:54:19 +01:00
TODO_ASSERT_EQUALS ( " [test.cpp:6]: (error) Array ii[10] out of bounds \n " , " " , errout . str ( ) ) ;
2010-06-06 16:20:50 +02:00
}
2010-10-11 20:52:14 +02:00
void array_index_30 ( )
{
// ticket #2086 - unknown type
check ( " void f() { \n "
" UINT8 x[2]; \n "
" x[5] = 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Array 'x[2]' index 5 out of bounds \n " , errout . str ( ) ) ;
}
2010-10-23 08:49:03 +02:00
void array_index_31 ( )
{
// ticket #2120 - sub function, unknown type
check ( " struct s1 { \n "
" unknown_type_t delay[3]; \n "
" }; \n "
" \n "
" void x(unknown_type_t *delay, const int *net) { \n "
" delay[0] = 0; \n "
" } \n "
" \n "
" void y() { \n "
" struct s1 obj; \n "
" x(obj.delay, 123); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct s1 { \n "
" unknown_type_t delay[3]; \n "
" }; \n "
" \n "
" void x(unknown_type_t *delay, const int *net) { \n "
" delay[4] = 0; \n "
" } \n "
" \n "
" void y() { \n "
" struct s1 obj; \n "
" x(obj.delay, 123); \n "
" } \n " ) ;
2011-09-20 02:32:50 +02:00
ASSERT_EQUALS ( " [test.cpp:11] -> [test.cpp:6]: (error) Array 'obj.delay[3]' index 4 out of bounds \n " , errout . str ( ) ) ;
2010-10-26 20:05:34 +02:00
check ( " struct s1 { \n "
" float a[0]; \n "
" }; \n "
" \n "
" void f() { \n "
" struct s1 *obj; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-10-23 08:49:03 +02:00
}
2011-01-31 13:46:51 +01:00
void array_index_32 ( )
{
check ( " class X \n "
" { \n "
" public: \n "
2011-01-31 17:26:07 +01:00
" X() \n "
2011-01-31 13:46:51 +01:00
" { \n "
" m_x[0] = 0; \n "
" m_x[1] = 0; \n "
" } \n "
" int m_x[1]; \n "
" }; \n " ) ;
2011-09-05 03:39:52 +02:00
ASSERT_EQUALS ( " [test.cpp:7]: (error) Array 'm_x[1]' index 1 out of bounds \n " , errout . str ( ) ) ;
2011-01-31 13:46:51 +01:00
}
2011-08-28 17:40:55 +02:00
void array_index_33 ( )
{
check ( " void foo(char bar[][4]) { \n "
" baz(bar[5]); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2011-09-03 01:35:09 +02:00
void array_index_34 ( ) // ticket #3063
{
check ( " void foo() { \n "
" int y[2][2][2]; \n "
" y[0][2][0] = 0; \n "
" y[0][0][2] = 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Array 'y[2][2][2]' index y[0][2][0] out of bounds \n "
" [test.cpp:4]: (error) Array 'y[2][2][2]' index y[0][0][2] out of bounds \n " , errout . str ( ) ) ;
2011-09-04 03:51:00 +02:00
check ( " struct TEST \n "
" { \n "
" char a[10]; \n "
" char b[10][5]; \n "
" }; \n "
" void foo() \n "
" { \n "
" TEST test; \n "
" test.a[10] = 3; \n "
" test.b[10][2] = 4; \n "
" test.b[0][19] = 4; \n "
" TEST *ptest; \n "
" ptest = &test; \n "
" ptest->a[10] = 3; \n "
" ptest->b[10][2] = 4; \n "
" ptest->b[0][19] = 4; \n "
" } \n " ) ;
2011-09-12 02:42:57 +02:00
ASSERT_EQUALS ( " [test.cpp:9]: (error) Array 'test.a[10]' index 10 out of bounds \n "
" [test.cpp:14]: (error) Array 'ptest.a[10]' index 10 out of bounds \n "
" [test.cpp:10]: (error) Array 'test.b[10][5]' index test.b[10][2] out of bounds \n "
" [test.cpp:11]: (error) Array 'test.b[10][5]' index test.b[0][19] out of bounds \n "
" [test.cpp:15]: (error) Array 'ptest.b[10][5]' index ptest.b[10][2] out of bounds \n "
" [test.cpp:16]: (error) Array 'ptest.b[10][5]' index ptest.b[0][19] out of bounds \n " , errout . str ( ) ) ;
2011-09-05 01:54:57 +02:00
check ( " struct TEST \n "
" { \n "
" char a[10][5]; \n "
" }; \n "
" void foo() \n "
" { \n "
" TEST test; \n "
" test.a[9][5] = 4; \n "
" test.a[0][50] = 4; \n "
" TEST *ptest; \n "
" ptest = &test; \n "
" ptest->a[9][5] = 4; \n "
" ptest->a[0][50] = 4; \n "
" } \n " ) ;
2011-09-12 02:42:57 +02:00
ASSERT_EQUALS ( " [test.cpp:8]: (error) Array 'test.a[10][5]' index test.a[9][5] out of bounds \n "
" [test.cpp:9]: (error) Array 'test.a[10][5]' index test.a[0][50] out of bounds \n "
" [test.cpp:12]: (error) Array 'ptest.a[10][5]' index ptest.a[9][5] out of bounds \n "
" [test.cpp:13]: (error) Array 'ptest.a[10][5]' index ptest.a[0][50] out of bounds \n " , errout . str ( ) ) ;
2011-09-05 01:54:57 +02:00
}
void array_index_35 ( ) // ticket #2889
{
check ( " void f() { \n "
" struct Struct { unsigned m_Var[1]; } s; \n "
" s.m_Var[1] = 1; \n "
" } \n " ) ;
2011-09-12 01:21:13 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Array 's.m_Var[1]' index 1 out of bounds \n " , errout . str ( ) ) ;
2011-09-05 01:54:57 +02:00
check ( " struct Struct { unsigned m_Var[1]; }; \n "
" void f() { \n "
" struct Struct s; \n "
" s.m_Var[1] = 1; \n "
" } \n " ) ;
2011-09-12 01:21:13 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 's.m_Var[1]' index 1 out of bounds \n " , errout . str ( ) ) ;
2011-09-05 01:54:57 +02:00
check ( " struct Struct { unsigned m_Var[1]; }; \n "
" void f() { \n "
" struct Struct * s = calloc(40); \n "
" s->m_Var[1] = 1; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-09-03 01:35:09 +02:00
}
2011-09-12 03:51:05 +02:00
void array_index_36 ( ) // ticket #2960
{
check ( " class Fred { \n "
" Fred(const Fred &); \n "
" private: \n "
" bool m_b[2]; \n "
" }; \n "
" Fred::Fred(const Fred & rhs) { \n "
" m_b[2] = rhs.m_b[2]; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:7]: (error) Array 'm_b[2]' index 2 out of bounds \n "
" [test.cpp:7]: (error) Array 'rhs.m_b[2]' index 2 out of bounds \n " , errout . str ( ) ) ;
}
2011-09-23 03:23:40 +02:00
void array_index_37 ( )
{
check ( " class Fred { \n "
" char x[X]; \n "
" Fred() { \n "
" for (unsigned int i = 0; i < 15; i++) \n "
" i; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , 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 " ) ;
2011-09-03 01:35:09 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'a[10][10][10]' index a[6][12][2] out of bounds \n " , errout . str ( ) ) ;
2010-04-23 21:56:35 +02:00
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
2011-08-05 13:08:48 +02:00
// unknown dim..
check ( " void f() \n "
" { \n "
" int a[2][countof(x)] = {{1,2},{3,4}}; \n "
" a[0][0] = 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
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 " ) ;
2011-01-30 12:54:19 +01:00
TODO_ASSERT_EQUALS ( " [test.cpp:12]: (error) Array index out of bounds \n " , " " , errout . str ( ) ) ;
2009-11-25 21:40:51 +01:00
}
2011-03-08 19:49:56 +01:00
void array_index_for_in_for ( )
{
check ( " void f() { \n "
" int a[5]; \n "
" for (int i = 0; i < 10; ++i) { \n "
" for (int j = i; j < 5; ++j) { \n "
" a[i] = 0; \n "
" } \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , 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 " ) ;
2010-11-05 20:35:31 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'data[8]' index 17 out of bounds \n " , errout . str ( ) ) ;
2010-11-21 12:24:57 +01:00
// #2199 - false negative: array out of bounds in loop when there is calculation
check ( " void f() \n "
" { \n "
" char arr[5]; \n "
" for (int i = 0; i < 5; ++i) { \n "
" arr[i + 7] = 0; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'arr[5]' index 11 out of bounds \n " , errout . str ( ) ) ;
2010-01-03 15:49:17 +01:00
}
2011-09-03 03:07:29 +02:00
void array_index_negative1 ( )
2010-01-11 21:18:07 +01:00
{
// #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-05-19 19:23:09 +02:00
check ( " void foo() \n "
" { \n "
" char s[] = \" abc \" ; \n "
" char *p = s + strlen(s); \n "
" if (p[-1]); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-07-14 12:24:07 +02:00
// ticket #1850
check ( " int f(const std::map<int, std::map<int,int> > &m) \n "
" { \n "
" return m[0][-1]; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-01-11 21:18:07 +01:00
}
2011-09-03 03:07:29 +02:00
void array_index_negative2 ( ) // ticket #3063
{
check ( " struct TEST { char a[10]; }; \n "
" void foo() { \n "
" TEST test; \n "
" test.a[-1] = 3; \n "
" } \n " ) ;
2011-09-12 02:42:57 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'test.a[10]' index -1 out of bounds \n " , errout . str ( ) ) ;
2011-09-03 03:07:29 +02: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 " ) ;
2011-01-30 12:54:19 +01: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 ( ) ) ;
}
2010-12-19 10:39:43 +01:00
void array_index_for_break ( )
{
check ( " void f() { \n "
" int a[2]; \n "
" for (int i = 0; i <= 2; ++i) { \n "
" a[i] = 0; \n "
" if (i==1) { \n "
" break; \n "
" } \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-12-28 20:46:31 +01:00
void array_index_for ( )
{
// Ticket #2370 - No false negative when there is no "break"
check ( " void f() { \n "
" int a[10]; \n "
" for (int i = 0; i < 20; ++i) { \n "
" if (i==1) { \n "
" } \n "
" a[i] = 0; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (error) Buffer access out-of-bounds: a \n " , errout . str ( ) ) ;
2010-12-31 17:43:38 +01:00
// Ticket #2385 - No false positive
check ( " void f() { \n "
" int a[10]; \n "
" for (int i = 0; i < 20; ++i) { \n "
" if (i<10) { \n "
" } else { \n "
" a[i-10] = 0; \n "
" } \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-12-28 20:46:31 +01:00
}
2011-01-09 18:51:28 +01:00
void array_index_for_neq ( )
{
// Ticket #2211 - for loop using != in the condition
check ( " void f() { \n "
" int a[5]; \n "
" for (int i = 0; i != 10; ++i) { \n "
" a[i] = 0; \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer access out-of-bounds: a \n " , errout . str ( ) ) ;
}
2010-12-19 10:39:43 +01:00
2011-02-12 11:31:10 +01:00
void array_index_for_question ( )
{
// Ticket #2561 - using ?: inside for loop
check ( " void f() { \n "
" int a[10]; \n "
" for (int i = 0; i != 10; ++i) { \n "
" i == 0 ? 0 : a[i-1]; \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2011-05-07 11:34:48 +02:00
void array_index_extern ( )
{
// Ticket #1684. FP when using 'extern'.
check ( " extern char arr[15]; \n "
" char arr[15] = \" abc \" ; " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2011-06-29 18:44:05 +02:00
void array_index_cast ( )
{
// Ticket #2841. FP when using cast.
// Different types => no error
check ( " void f1(char *buf) { \n "
" buf[4] = 0; \n "
" } \n "
" void f2() { \n "
" int x[2]; \n "
" f1(x); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// Same type => error
check ( " void f1(const char buf[]) { \n "
" char c = buf[4]; \n "
" } \n "
" void f2() { \n "
" char x[2]; \n "
" f1(x); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:6] -> [test.cpp:2]: (error) Array 'x[2]' index 4 out of bounds \n " , 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-11-07 17:42:32 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Buffer access out-of-bounds: str \n " , errout . str ( ) ) ;
2010-04-06 20:56:01 +02:00
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-11-07 17:42:32 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Buffer access out-of-bounds: str \n " , errout . str ( ) ) ;
2010-04-06 20:56:01 +02:00
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 ( ) ) ;
2010-08-14 20:19:23 +02:00
check ( " void f() \n "
" { \n "
" char str[3]; \n "
" recv(s, str, 4, 0); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer access out-of-bounds: str \n " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" char str[3]; \n "
" recvfrom(s, str, 4, 0, 0x0, 0x0); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer access out-of-bounds: str \n " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" char str[3]; \n "
" send(s, str, 4, 0); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer access out-of-bounds: str \n " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" char str[3]; \n "
" sendto(s, str, 4, 0, 0x0, 0x0); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer access out-of-bounds: str \n " , 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 ( ) ) ;
2011-09-09 04:41:18 +02:00
check ( " struct ABC \n "
" { \n "
" char str[5]; \n "
" }; \n "
" \n "
" static void f() \n "
" { \n "
" struct ABC abc; \n "
" strcpy( abc.str, \" abcdef \" ); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:9]: (error) Buffer access out-of-bounds: abc.str \n " , errout . str ( ) ) ;
check ( " struct ABC \n "
" { \n "
" char str[5]; \n "
" }; \n "
" \n "
" static void f(struct ABC &abc) \n "
" { \n "
" strcpy( abc.str, \" abcdef \" ); \n "
" } \n " ) ;
2011-09-09 04:44:25 +02:00
ASSERT_EQUALS ( " [test.cpp:8]: (error) Buffer access out-of-bounds: abc.str \n " , errout . str ( ) ) ;
2011-09-09 04:41:18 +02:00
check ( " static void f() \n "
" { \n "
" struct ABC \n "
" { \n "
" char str[5]; \n "
" } abc; \n "
" strcpy( abc.str, \" abcdef \" ); \n "
" } \n " ) ;
2011-09-09 13:16:39 +02:00
ASSERT_EQUALS ( " [test.cpp:7]: (error) Buffer access out-of-bounds: abc.str \n " , errout . str ( ) ) ;
2011-09-09 04:41:18 +02:00
check ( " static void f() \n "
" { \n "
" struct ABC \n "
" { \n "
" char str[5]; \n "
" }; \n "
" struct ABC *abc = malloc(sizeof(struct ABC)); \n "
" strcpy( abc->str, \" abcdef \" ); \n "
" free(abc); \n "
" } \n " ) ;
2011-09-09 13:16:39 +02: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 " ) ;
2011-01-30 12:54:19 +01:00
TODO_ASSERT_EQUALS ( " [test.cpp:8] -> [test.cpp:3]: (error) Buffer access out-of-bounds \n " , " " , 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 ( ) ) ;
}
2010-05-26 10:56:34 +02:00
void buffer_overrun_14 ( )
{
check ( " void f(char *a) { \n "
" char *b = new char[strlen(a)]; \n "
" strcpy(b, a); \n "
" return b; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Buffer access out-of-bounds \n " , errout . str ( ) ) ;
2010-05-26 19:21:34 +02:00
2010-05-26 10:56:34 +02:00
check ( " void f(char *a) { \n "
" char *b = new char[strlen(a) + 1]; \n "
" strcpy(b, a); \n "
" return b; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-05-26 19:21:34 +02:00
2010-05-26 10:56:34 +02:00
check ( " void f(char *a) { \n "
" char *b = new char[strlen(a)]; \n "
" a[0] = ' \\ 0'; \n "
" strcpy(b, a); \n "
" return b; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-05-26 19:21:34 +02:00
2010-05-26 10:56:34 +02:00
check ( " void f(char *a) { \n "
" char *b = malloc(strlen(a)); \n "
" b = realloc(b, 10000); \n "
" strcpy(b, a); \n "
" return b; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(char *a) { \n "
" char *b = malloc(strlen(a)); \n "
" strcpy(b, a); \n "
" return b; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Buffer access out-of-bounds \n " , errout . str ( ) ) ;
2010-05-26 19:21:34 +02:00
2010-05-26 10:56:34 +02:00
check ( " void f(char *a) { \n "
" char *b = malloc(strlen(a)); \n "
" if (1) { \n "
" strcpy(b, a); \n "
" } \n "
" return b; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer access out-of-bounds \n " , errout . str ( ) ) ;
2010-05-26 19:21:34 +02:00
2010-05-26 10:56:34 +02:00
check ( " void f(char *a) { \n "
" char *b = malloc(strlen(a) + 1); \n "
" strcpy(b, a); \n "
" return b; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-05-26 19:21:34 +02:00
2010-05-26 10:56:34 +02:00
check ( " void f(char *a, char *c) { \n "
" char *b = realloc(c, strlen(a)); \n "
" strcpy(b, a); \n "
" return b; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Buffer access out-of-bounds \n " , errout . str ( ) ) ;
2010-05-26 19:21:34 +02:00
2010-05-26 10:56:34 +02:00
check ( " void f(char *a, char *c) { \n "
" char *b = realloc(c, strlen(a) + 1); \n "
" strcpy(b, a); \n "
" return b; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-05-26 19:21:34 +02:00
2010-05-26 10:56:34 +02:00
check ( " void f(char *a) { \n "
" char *b = malloc(strlen(a)); \n "
" sprintf(b, \" %s \" , a); \n "
" return b; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Buffer access out-of-bounds \n " , errout . str ( ) ) ;
}
2010-06-13 07:17:50 +02:00
void buffer_overrun_15 ( ) // ticket #1787
{
check ( " class A : public B { \n "
" char val[12]; \n "
" void f(int i, int ii); \n "
" }; \n "
" void A::f(int i, int ii) \n "
" { \n "
" sprintf(val, \" drive_%d_partition_%d_size \" , i, ii) ; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:7]: (error) Buffer access out-of-bounds \n " , errout . str ( ) ) ;
}
2010-10-12 19:35:20 +02:00
void buffer_overrun_16 ( )
{
2010-10-13 18:06:50 +02:00
// unknown types
2010-10-12 19:35:20 +02:00
check ( " void f() { \n "
" struct Foo foo[5]; \n "
" memset(foo, 0, sizeof(foo)); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-10-13 18:06:50 +02:00
check ( " void f() { \n " // ticket #2093
" gchar x[3]; \n "
" strcpy(x, \" 12 \" ); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-10-13 20:57:59 +02:00
check ( " extern char a[10]; \n "
" void f() { \n "
" char b[25] = {0}; \n "
" std::memcpy(b, a, sizeof(a)); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-10-12 19:35:20 +02:00
}
2011-02-11 18:57:58 +01:00
void buffer_overrun_17 ( ) // ticket #2548
{
check ( " void f() { \n "
" char t[8]; \n "
" sprintf(t, \" %s \" , \" foo bar \" ); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Buffer access out-of-bounds \n " , errout . str ( ) ) ;
}
2011-02-12 18:34:12 +01:00
void buffer_overrun_18 ( ) // ticket #2576
{
check ( " class A { \n "
" void foo(); \n "
" bool b[7]; \n "
" }; \n "
" \n "
" void A::foo() { \n "
" for (int i=0; i<6; i++) { \n "
" b[i] = b[i+1]; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-02-13 22:48:26 +01:00
check ( " class A { \n "
" void foo(); \n "
" bool b[7]; \n "
" }; \n "
" \n "
" void A::foo() { \n "
" for (int i=0; i<7; i++) { \n "
" b[i] = b[i+1]; \n "
" } \n "
" } \n " ) ;
2011-09-04 03:51:00 +02:00
ASSERT_EQUALS ( " [test.cpp:8]: (error) Array 'b[7]' index 7 out of bounds \n " , errout . str ( ) ) ;
2011-02-12 18:34:12 +01:00
}
2011-02-20 21:24:57 +01:00
void buffer_overrun_19 ( ) // #2597 - class member with unknown type
{
check ( " class A { \n "
" public: \n "
" u8 buf[10]; \n "
" A(); "
" }; \n "
" \n "
" A::A() { \n "
" memset(buf, 0, 10); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2011-08-10 01:45:18 +02:00
void buffer_overrun_20 ( ) // #2986(segmentation fault)
{
check ( " x[y] \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2011-08-24 12:53:27 +02:00
void buffer_overrun_21 ( )
{
check ( " void foo() \n "
" { { { \n "
" char dst[4]; \n "
" const char *src = \" AAAAAAAAAAAAAAAAAAAAA \" ; \n "
" for (size_t i = 0; i <= 4; i++) \n "
" dst[i] = src[i]; \n "
" } } } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (error) Buffer access out-of-bounds: dst \n " , errout . str ( ) ) ;
}
2011-09-20 02:32:50 +02:00
void buffer_overrun_22 ( ) // ticket #3124
{
check ( " class A { \n "
" public: \n "
" char b[5][6]; \n "
" }; \n "
" int main() { \n "
" A a; \n "
" memset(a.b, 0, 5 * 6); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " class A { \n "
" public: \n "
" char b[5][6]; \n "
" }; \n "
" int main() { \n "
" A a; \n "
" memset(a.b, 0, 6 * 6); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:7]: (error) Buffer access out-of-bounds: a.b \n " , errout . str ( ) ) ;
}
2011-09-30 23:28:59 +02:00
void buffer_overrun_23 ( ) // ticket #3153
{
check ( " void foo() { \n "
" double dest = 23.0; \n "
" char* const source = (char*) malloc(sizeof(dest)); \n "
" memcpy(&dest, source + sizeof(double), sizeof(dest)); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer access out-of-bounds \n " , errout . str ( ) ) ;
check ( " void foo() { \n "
" double dest = 23.0; \n "
" char* const source = (char*) malloc(2 * sizeof(dest)); \n "
" memcpy(&dest, source + sizeof(double), sizeof(dest)); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-12-31 18:07:46 +01:00
void buffer_overrun_bailoutIfSwitch ( )
{
// No false positive
check ( " void f1(char *s) { \n "
" if (x) s[100] = 0; \n "
" } \n "
" \n "
" void f2() { \n "
" char a[10]; \n "
" f1(a); "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// No false positive
check ( " void f1(char *s) { \n "
" if (x) return; \n "
" s[100] = 0; \n "
" } \n "
" \n "
" void f2() { \n "
" char a[10]; \n "
" f1(a); "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// No false negative
check ( " void f1(char *s) { \n "
" if (x) { } \n "
" s[100] = 0; \n "
" } \n "
" \n "
" void f2() { \n "
" char a[10]; \n "
" f1(a); "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:8] -> [test.cpp:3]: (error) Array 'a[10]' index 100 out of bounds \n " , errout . str ( ) ) ;
}
2011-08-21 20:44:55 +02:00
void possible_buffer_overrun_1 ( ) // #3035
{
check ( " void foo() { \n "
" char * data = (char *)alloca(50); \n "
" char src[100]; \n "
" memset(src, 'C', 100-1); \n "
" src[100-1] = ' \\ 0'; \n "
" strcat(data, src); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (warning) Possible buffer overflow if strlen(src) is larger than sizeof(data)-strlen(data). \n " , errout . str ( ) ) ;
check ( " void foo() { \n "
" char * data = (char *)alloca(100); \n "
" char src[100]; \n "
" memset(src, 'C', 100-1); \n "
" src[100-1] = ' \\ 0'; \n "
" strcat(data, src); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo(char src[100]) { \n "
" char * data = (char *)alloca(50); \n "
" strcat(data, src); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (warning) Possible buffer overflow if strlen(src) is larger than sizeof(data)-strlen(data). \n " , errout . str ( ) ) ;
check ( " void foo(char src[100]) { \n "
" char * data = (char *)alloca(100); \n "
" strcat(data, src); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-08-21 21:18:41 +02:00
check ( " void foo() { \n "
" char * data = (char *)alloca(50); \n "
" char src[100]; \n "
" memset(src, 'C', 100-1); \n "
" src[100-1] = ' \\ 0'; \n "
" strcpy(data, src); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (warning) Possible buffer overflow if strlen(src) is larger than or equal to sizeof(data). \n " , errout . str ( ) ) ;
check ( " void foo() { \n "
" char * data = (char *)alloca(100); \n "
" char src[100]; \n "
" memset(src, 'C', 100-1); \n "
" src[100-1] = ' \\ 0'; \n "
" strcpy(data, src); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo(char src[100]) { \n "
" char * data = (char *)alloca(50); \n "
" strcpy(data, src); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (warning) Possible buffer overflow if strlen(src) is larger than or equal to sizeof(data). \n " , errout . str ( ) ) ;
check ( " void foo(char src[100]) { \n "
" char * data = (char *)alloca(100); \n "
" strcpy(data, src); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-08-21 20:44:55 +02:00
}
2010-12-26 21:23:28 +01:00
void pointer_out_of_bounds_1 ( )
{
check ( " void f() { \n "
" char a[10]; \n "
" char *p = a + 100; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (portability) Undefined behaviour: pointer arithmetic result does not point into or just past the end of the array \n " , errout . str ( ) ) ;
}
2011-01-01 20:56:21 +01:00
void pointer_out_of_bounds_2 ( )
{
check ( " void f() { \n "
" char *p = malloc(10); \n "
" p += 100; \n "
" free(p); "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (portability) Undefined behaviour: pointer arithmetic result does not point into or just past the end of the buffer \n " , errout . str ( ) ) ;
check ( " void f() { \n "
" char *p = malloc(10); \n "
" p += 10; \n "
" *p = 0; \n "
" free(p); "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) p is out of bounds \n " , errout . str ( ) ) ;
2011-10-12 20:54:39 +02:00
check ( " void f() { \n "
" char *p = malloc(10); \n "
" p += 10; \n "
" p -= 10; \n "
" *p = 0; \n "
" free(p); "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-01-01 20:56:21 +01:00
check ( " void f() { \n "
" char *p = malloc(10); \n "
" p += 10; \n "
" p = p - 1 \n "
" *p = 0; \n "
" free(p); "
" } " ) ;
ASSERT_EQUALS ( " " , 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 " ) ;
2011-01-30 12:54:19 +01:00
TODO_ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer access out-of-bounds \n " , " " , errout . str ( ) ) ;
2009-09-26 19:40:58 +02:00
}
2010-05-29 11:19:56 +02:00
2010-05-29 07:51:28 +02:00
void sprintf7 ( )
{
check ( " struct Foo { char a[1]; }; \n "
" void f() \n "
" { \n "
" struct Foo x; \n "
" sprintf(x.a, \" aa \" ); \n "
" } \n " ) ;
2011-09-09 13:46:06 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Buffer access out-of-bounds \n " , errout . str ( ) ) ;
check ( " struct Foo { char a[1]; }; \n "
" void f() \n "
" { \n "
2011-09-09 14:37:24 +02:00
" struct Foo *x = malloc(sizeof(Foo)); \n "
" sprintf(x.a, \" aa \" ); \n "
" free(x); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (error) Buffer access out-of-bounds \n " , errout . str ( ) ) ;
check ( " struct Foo { char a[1]; }; \n "
" void f() \n "
" { \n "
" struct Foo *x = malloc(sizeof(Foo) + 10); \n "
2011-09-09 13:46:06 +02:00
" sprintf(x.a, \" aa \" ); \n "
" free(x); \n "
" } \n " ) ;
2010-11-06 09:10:10 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-05-29 07:51:28 +02:00
}
2010-05-29 11:19:56 +02:00
2010-05-29 07:51:28 +02:00
void sprintf8 ( )
{
check ( " struct Foo { char a[3]; }; \n "
" void f() \n "
" { \n "
" struct Foo x; \n "
" sprintf(x.a, \" aa \" ); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-09-26 19:40:58 +02:00
2010-10-19 18:23:44 +02:00
void sprintf9 ( )
{
check ( " void f() \n "
" { \n "
" gchar str[3]; \n "
" sprintf(str, \" 1 \" ); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-10-22 20:15:51 +02:00
void sprintf10 ( )
{
check ( " void f() \n "
" { \n "
" TString str = \" \" ; \n "
" sprintf(str, \" 1 \" ); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
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 " ) ;
2011-10-05 20:17:57 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) snprintf size is out of bounds: Supplied size 10 is larger than actual size of 5 \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
}
2010-05-29 07:51:28 +02:00
void snprintf5 ( )
{
check ( " struct Foo { char a[1]; }; \n "
" void f() \n "
" { \n "
" struct Foo x; \n "
" snprintf(x.a, 2, \" aa \" ); \n "
" } \n " ) ;
2011-10-05 20:17:57 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) snprintf size is out of bounds: Supplied size 2 is larger than actual size of 1 \n " , errout . str ( ) ) ;
2011-09-09 13:46:06 +02:00
check ( " struct Foo { char a[1]; }; \n "
" void f() \n "
" { \n "
2011-09-09 14:37:24 +02:00
" struct Foo *x = malloc(sizeof(Foo)); \n "
" snprintf(x.a, 2, \" aa \" ); \n "
" free(x); \n "
" } \n " ) ;
2011-10-05 20:17:57 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) snprintf size is out of bounds: Supplied size 2 is larger than actual size of 1 \n " , errout . str ( ) ) ;
2011-09-09 14:37:24 +02:00
check ( " struct Foo { char a[1]; }; \n "
" void f() \n "
" { \n "
" struct Foo *x = malloc(sizeof(Foo) + 10); \n "
2011-09-09 13:46:06 +02:00
" snprintf(x.a, 2, \" aa \" ); \n "
" free(x); \n "
" } \n " ) ;
2010-11-06 09:10:10 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-05-29 07:51:28 +02:00
}
2010-05-29 11:19:56 +02:00
2010-05-29 07:51:28 +02:00
void snprintf6 ( )
{
check ( " struct Foo { char a[3]; }; \n "
" void f() \n "
" { \n "
" struct Foo x; \n "
" snprintf(x.a, 2, \" aa \" ); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2008-12-18 22:28:57 +01:00
2010-11-18 19:26:46 +01:00
void snprintf7 ( )
{
check ( " void x() { \n "
" const int nBezString = 1024; \n "
" sal_Char pString[nBezString]; \n "
" snprintf(pString, nBezString, \" ab \" ); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
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 " ) ;
2011-01-03 17:33:03 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (warning) Dangerous usage of strncat - 3rd parameter is the 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 " ) ;
2011-01-03 17:33:03 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (warning) Dangerous usage of strncat - 3rd parameter is the maximum number of characters to append. \n " , errout . str ( ) ) ;
2009-02-20 21:00:49 +01:00
}
2010-05-29 07:51:28 +02:00
void strncat3 ( )
{
check ( " struct Foo { char a[4]; }; \n "
" void f(char *a) \n "
" { \n "
" struct Foo x; \n "
" strncat(x.a, a, 5); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (error) Buffer access out-of-bounds: x.a \n " , errout . str ( ) ) ;
}
void strcat1 ( )
{
check ( " struct Foo { char a[4]; }; \n "
" void f() \n "
" { \n "
" struct Foo x; \n "
" strcat(x.a, \" aa \" ); \n "
" strcat(x.a, \" aa \" ); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (error) Buffer access out-of-bounds \n " , errout . str ( ) ) ;
}
2010-05-29 11:19:56 +02:00
2010-05-29 07:51:28 +02:00
void strcat2 ( )
{
check ( " struct Foo { char a[5]; }; \n "
" void f() \n "
" { \n "
" struct Foo x; \n "
" strcat(x.a, \" aa \" ); \n "
" strcat(x.a, \" aa \" ); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-02-20 21:00:49 +01:00
2010-12-18 10:54:36 +01:00
void strcat3 ( )
{
check ( " void f() { \n "
" INT str[10]; \n "
" strcat(str, \" aa \" ); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-02-20 21:00:49 +01:00
2010-04-05 20:02:28 +02:00
// memchr/memset/memcpy/etc
2010-10-23 13:12:17 +02:00
void memfunc1 ( )
2010-04-05 20:02:28 +02:00
{
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 " ) ;
2011-01-30 12:54:19 +01:00
TODO_ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer access out-of-bounds \n " , " " , errout . str ( ) ) ;
2010-04-05 20:02:28 +02:00
}
2010-10-23 13:12:17 +02:00
// ticket #2121 - buffer access out of bounds when using uint32_t
void memfunc2 ( )
{
check ( " void f() \n "
" { \n "
" unknown_type_t buf[4]; \n "
" memset(buf, 0, 100); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-04-05 20:02:28 +02: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 " ) ;
2010-08-04 20:38:52 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 's[10]' index 10 out of bounds \n " , errout . str ( ) ) ;
// ticket #1670 - false negative when using return
2011-09-11 20:00:53 +02:00
check ( " char f() \n "
2010-08-04 20:38:52 +02:00
" { \n "
" char *s = new int[10]; \n "
" return s[10]; \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 ( ) ) ;
2011-09-11 20:00:53 +02:00
check ( " struct Fred { char c[10]; }; \n "
" char f() \n "
" { \n "
" Fred *f = new Fred; \n "
" return f->c[10]; \n "
" } \n " ) ;
2011-09-12 01:21:13 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'f.c[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
2010-10-10 09:15:18 +02:00
// statically allocated buffer
void alloc3 ( )
{
check ( " void foo() \n "
" { \n "
" const char *s = \" 123 \" ; \n "
" s[10] = 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 's[4]' index 10 out of bounds \n " , errout . str ( ) ) ;
2010-11-06 09:10:10 +01:00
check ( " void foo() \n "
" { \n "
" char *s; s = \" \" ; \n "
" s[10] = 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 's[1]' index 10 out of bounds \n " , errout . str ( ) ) ;
2011-08-08 18:22:15 +02:00
check ( " void foo() { \n "
" const char *s = \" \" ; \n "
" s = y(); \n "
" s[10] = 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-10-10 09:15:18 +02:00
}
2011-07-17 09:35:51 +02:00
// data is allocated with alloca
void alloc4 ( )
{
check ( " void foo() \n "
" { \n "
" char *s = (char *)alloca(10); \n "
" s[10] = 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 's[10]' index 10 out of bounds \n " , errout . str ( ) ) ;
}
2011-01-22 21:31:26 +01:00
void malloc_memset ( )
{
check ( " void f() { \n "
" char *p = malloc(10); \n "
" memset(p,0,100); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Buffer access 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 " ) ;
2010-10-17 14:41:00 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (warning) 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 ) ) ;
2011-01-30 12:54:19 +01:00
TODO_ASSERT_EQUALS ( 5 , 2 , CheckBufferOverrun : : countSprintfLength ( " %x " , intAsParameter ) ) ;
2009-10-19 23:48:29 +02:00
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 ) ;
2011-01-30 12:54:19 +01:00
TODO_ASSERT_EQUALS ( 5 , 3 , CheckBufferOverrun : : countSprintfLength ( " %.2f " , floatAsParameter ) ) ;
2009-10-08 16:36:00 +02:00
ASSERT_EQUALS ( 9 , CheckBufferOverrun : : countSprintfLength ( " %8.2f " , floatAsParameter ) ) ;
2011-01-30 12:54:19 +01:00
TODO_ASSERT_EQUALS ( 5 , 3 , CheckBufferOverrun : : countSprintfLength ( " %2.2f " , floatAsParameter ) ) ;
2009-10-08 16:36:00 +02:00
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 ) ;
2011-01-30 12:54:19 +01:00
TODO_ASSERT_EQUALS ( 7 , 3 , CheckBufferOverrun : : countSprintfLength ( " %2.2f " , floatAsParameter2 ) ) ;
TODO_ASSERT_EQUALS ( 7 , 3 , CheckBufferOverrun : : countSprintfLength ( " %.2f " , floatAsParameter ) ) ;
TODO_ASSERT_EQUALS ( 7 , 5 , 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 " ) ;
2011-09-05 21:19:38 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (warning) The buffer 'c' is not zero-terminated after the call to strncpy(). \n " , errout . str ( ) ) ;
2009-09-25 22:32:18 +02:00
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 " ) ;
2011-08-28 15:06:51 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (warning) The buffer 'baz' may not be zero-terminated after the call to strncpy(). \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 " ) ;
2011-08-28 15:06:51 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (warning) The buffer 'baz' may not be zero-terminated after the call to strncpy(). \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 " ) ;
2011-08-28 15:06:51 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (warning) The buffer 'baz' may not be zero-terminated after the call to strncpy(). \n " , errout . str ( ) ) ;
2009-12-18 17:26:15 +01:00
}
2010-11-07 09:37:45 +01:00
void terminateStrncpy3 ( )
{
// Ticket #2170 - false positive
// The function bar is risky. But it might work that way intentionally.
check ( " char str[100]; \n "
" \n "
" void foo(char *a) { \n "
" strncpy(str, a, 100); \n "
" } \n "
" \n "
" void bar(char *p) { \n "
" strncpy(p, str, 100); \n "
" } \n " , false ) ;
2011-08-28 15:06:51 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (warning) The buffer 'str' may not be zero-terminated after the call to strncpy(). \n " , errout . str ( ) ) ;
2010-11-07 09:37:45 +01:00
}
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
2011-03-09 21:00:28 +01:00
void crash1 ( )
2010-04-11 20:57:30 +02:00
{
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 ( ) ) ;
}
2011-03-09 21:00:28 +01:00
void crash2 ( )
{
check ( " struct C {} {} x " ) ;
}
2010-04-11 20:57:30 +02:00
2011-08-29 19:16:52 +02:00
void crash3 ( )
{
check ( " void a(char *p) { \n "
" f( { if(finally_arg); } ); \n "
" } \n "
" \n "
" void b() { \n "
" char arr[64]; \n "
" a(arr); \n "
" } " ) ;
}
2010-04-10 21:12:00 +02:00
void epcheck ( const char code [ ] )
{
2010-12-01 18:00:55 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
Settings settings ;
2010-04-10 21:12:00 +02:00
// Tokenize..
2010-12-01 18:00:55 +01:00
Tokenizer tokenizer ( & settings , this ) ;
2010-04-10 21:12:00 +02:00
std : : istringstream istr ( code ) ;
tokenizer . tokenize ( istr , " test.cpp " ) ;
tokenizer . simplifyTokenList ( ) ;
// Check for buffer overruns..
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
}
2010-06-02 18:09:25 +02:00
2010-07-05 22:19:27 +02:00
void executionPaths2 ( )
{
epcheck ( " void foo() \n "
" { \n "
" char a[64]; \n "
" int sz = sizeof(a); \n "
" bar(&sz); \n "
" a[sz] = 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-10-30 12:32:43 +02:00
void executionPaths3 ( )
{
epcheck ( " void f(char *VLtext) \n "
" { \n "
" if ( x ) { \n "
" return VLtext[0]; \n "
" } else { \n "
" int wordlen = ab(); \n "
" VLtext[wordlen] = 0; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-12-31 20:55:28 +01:00
void executionPaths4 ( )
{
// Ticket #2386 - Segmentation fault upon strange syntax
epcheck ( " void f() { \n "
" switch ( x ) { \n "
" case struct Tree : break; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2011-07-20 07:57:42 +02:00
void executionPaths5 ( )
{
// No false positive
epcheck ( " class A { \n "
" void foo() { \n "
" int j = g(); \n "
" arr[j]=0; \n "
" } \n "
" \n "
" int arr[2*BSize + 2]; \n "
" }; \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-06-02 07:41:07 +02:00
void cmdLineArgs1 ( )
{
check ( " int main(int argc, char* argv[]) \n "
2010-06-02 18:09:25 +02:00
" { \n "
" char prog[10]; \n "
" strcpy(prog, argv[0]); \n "
" } \n " ) ;
2010-06-02 07:41:07 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer overrun possible for long cmd-line args \n " , errout . str ( ) ) ;
2010-06-02 18:09:25 +02:00
2010-06-02 07:41:07 +02:00
check ( " int main(int argc, char* argv[]) \n "
2010-06-02 18:09:25 +02:00
" { \n "
" char prog[10] = {' \\ 0'}; \n "
" strcat(prog, argv[0]); \n "
" } \n " ) ;
2010-06-02 07:41:07 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer overrun possible for long cmd-line args \n " , errout . str ( ) ) ;
2010-06-02 18:09:25 +02:00
2010-06-02 07:41:07 +02:00
check ( " int main(int argc, char* argv[]) \n "
2010-06-02 18:09:25 +02:00
" { \n "
" char prog[10]; \n "
" sprintf(prog, \" %s \" , argv[0]); \n "
" } \n " ) ;
2010-06-02 07:41:07 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer overrun possible for long cmd-line args \n " , errout . str ( ) ) ;
2010-06-02 18:09:25 +02:00
2010-06-02 07:41:07 +02:00
check ( " int main(int argc, char **argv, char **envp) \n "
2010-06-02 18:09:25 +02:00
" { \n "
" char prog[10]; \n "
" strcpy(prog, argv[0]); \n "
" } \n " ) ;
2010-06-02 07:41:07 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer overrun possible for long cmd-line args \n " , errout . str ( ) ) ;
2010-06-02 18:09:25 +02:00
2010-06-02 07:41:07 +02:00
check ( " int main(int argc, char **argv, char **envp) \n "
2010-06-02 18:09:25 +02:00
" { \n "
" char prog[10] = {' \\ 0'}; \n "
" strcat(prog, argv[0]); \n "
" } \n " ) ;
2010-06-02 07:41:07 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer overrun possible for long cmd-line args \n " , errout . str ( ) ) ;
2010-06-02 18:09:25 +02:00
2010-06-02 07:41:07 +02:00
check ( " int main(int argc, char **argv, char **envp) \n "
2010-06-02 18:09:25 +02:00
" { \n "
" char prog[10]; \n "
" sprintf(prog, \" %s \" , argv[0]); \n "
" } \n " ) ;
2010-06-02 07:41:07 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer overrun possible for long cmd-line args \n " , errout . str ( ) ) ;
2010-06-02 18:09:25 +02:00
2010-06-02 07:41:07 +02:00
check ( " int main(int argc, char **options) \n "
2010-06-02 18:09:25 +02:00
" { \n "
" char prog[10]; \n "
" strcpy(prog, options[0]); \n "
" } \n " ) ;
2010-06-02 07:41:07 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer overrun possible for long cmd-line args \n " , errout . str ( ) ) ;
2010-06-02 18:09:25 +02:00
2010-06-02 07:41:07 +02:00
check ( " int main(int argc, char **options) \n "
2010-06-02 18:09:25 +02:00
" { \n "
" char prog[10] = {' \\ 0'}; \n "
" strcat(prog, options[0]); \n "
" } \n " ) ;
2010-06-02 07:41:07 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer overrun possible for long cmd-line args \n " , errout . str ( ) ) ;
2010-06-02 18:09:25 +02:00
2010-06-02 07:41:07 +02:00
check ( " int main(int argc, char **options) \n "
2010-06-02 18:09:25 +02:00
" { \n "
" char prog[10]; \n "
" sprintf(prog, \" %s \" , *options); \n "
" } \n " ) ;
2010-06-02 07:41:07 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer overrun possible for long cmd-line args \n " , errout . str ( ) ) ;
2010-06-02 18:09:25 +02:00
2010-06-02 07:41:07 +02:00
check ( " int main(int argc, char **argv, char **envp) \n "
2010-06-02 18:09:25 +02:00
" { \n "
" char prog[10]; \n "
" if (strlen(argv[0]) < 10) \n "
" strcpy(prog, argv[0]); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-06-02 07:41:07 +02:00
check ( " int main(int argc, char **argv, char **envp) \n "
2010-06-02 18:09:25 +02:00
" { \n "
" char prog[10] = {' \\ 0'}; \n "
" if (10 > strlen(argv[0])) \n "
" strcat(prog, argv[0]); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-06-02 07:41:07 +02:00
check ( " int main(int argc, char **argv, char **envp) \n "
2010-06-02 18:09:25 +02:00
" { \n "
" char prog[10]; \n "
" sprintf(prog, \" %p \" , argv[0]); \n "
" } \n " ) ;
2010-06-02 07:41:07 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-06-02 18:09:25 +02:00
2010-06-02 07:41:07 +02:00
check ( " int main(int argc, char **argv, char **envp) \n "
2010-06-02 18:09:25 +02:00
" { \n "
" char prog[10]; \n "
" argv[0][0] = ' \\ 0'; \n "
" strcpy(prog, argv[0]); \n "
" } \n " ) ;
2010-06-02 07:41:07 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-08-24 22:03:18 +02:00
void scope ( )
{
check ( " class A { \n "
" private: \n "
" struct X { char buf[10]; }; \n "
" } \n "
" \n "
" void f() \n "
" { \n "
" X x; \n "
" x.buf[10] = 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-09-09 13:16:39 +02:00
check ( " class A { \n "
" public: \n "
" struct X { char buf[10]; }; \n "
" } \n "
" \n "
" void f() \n "
" { \n "
" A::X x; \n "
" x.buf[10] = 0; \n "
" } \n " ) ;
TODO_ASSERT_EQUALS ( " [test.cpp:9]: (error) Array 'x.buf[10]' index 10 out of bounds \n " , " " , errout . str ( ) ) ;
2010-08-24 22:03:18 +02:00
}
2010-12-13 18:17:33 +01:00
2010-12-16 20:15:22 +01:00
void getErrorMessages ( )
{
// Ticket #2292: segmentation fault when using --errorlist
CheckBufferOverrun c ;
2010-12-29 12:43:29 +01:00
c . getErrorMessages ( this , 0 ) ;
2010-12-16 20:15:22 +01:00
}
2011-03-13 17:52:45 +01:00
void unknownMacroNoDecl ( )
{
check ( " void f() { \n "
" int a[10]; \n "
" AAA a[0] = 0; \n " // <- not a valid array declaration
" a[1] = 1; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2011-08-04 11:15:14 +02:00
void arrayIndexThenCheck ( )
{
check ( " void f(const char s[]) { \n "
" if (s[i] == 'x' && i < y) { \n "
" } "
" } " ) ;
2011-08-05 09:10:07 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Array index i is used before limits check \n " , errout . str ( ) ) ;
2011-08-04 11:15:14 +02:00
check ( " void f(const char s[]) { \n "
" for (i = 0; s[i] == 'x' && i < y; ++i) { \n "
" } "
" } " ) ;
2011-08-05 09:10:07 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Array index i is used before limits check \n " , errout . str ( ) ) ;
2011-08-04 11:15:14 +02:00
}
2011-09-05 21:59:41 +02:00
void bufferNotZeroTerminated ( )
{
check ( " void f() \n "
" { \n "
" char c[6]; \n "
" strncpy(c, \" hello! \" ,sizeof(c)); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (warning) The buffer 'c' is not zero-terminated after the call to strncpy(). \n " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" char c[6]; \n "
" memcpy(c, \" hello! \" ,sizeof(c)); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (warning) The buffer 'c' is not zero-terminated after the call to memcpy(). \n " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" char c[6]; \n "
" memmove(c, \" hello! \" ,sizeof(c)); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (warning) The buffer 'c' is not zero-terminated after the call to memmove(). \n " , errout . str ( ) ) ;
}
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