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
2020-05-10 11:16:32 +02:00
* Copyright ( C ) 2007 - 2020 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
*/
2017-05-27 04:33:47 +02:00
2020-04-13 13:44:48 +02:00
# include "check.h"
2009-10-25 12:49:06 +01:00
# include "checkbufferoverrun.h"
2020-04-13 13:44:48 +02:00
# include "config.h"
# include "ctu.h"
2017-05-27 04:33:47 +02:00
# include "library.h"
# include "settings.h"
2008-12-18 22:28:57 +01:00
# include "testsuite.h"
2017-05-27 04:33:47 +02:00
# include "tokenize.h"
2008-12-18 22:28:57 +01:00
2015-02-09 16:20:28 +01:00
# include <tinyxml2.h>
2010-03-30 17:33:17 +02:00
# include <climits>
2017-05-27 04:33:47 +02:00
# include <list>
# include <ostream>
# include <string>
2008-12-18 22:28:57 +01:00
2011-10-13 20:53:06 +02:00
class TestBufferOverrun : public TestFixture {
2008-12-18 22:28:57 +01:00
public :
2014-11-20 14:20:09 +01:00
TestBufferOverrun ( ) : TestFixture ( " TestBufferOverrun " ) {
2013-08-07 16:27:37 +02:00
}
2008-12-18 22:28:57 +01:00
private :
2015-10-07 18:33:57 +02:00
Settings settings0 ;
2008-12-18 22:28:57 +01:00
2015-07-25 14:17:55 +02:00
void check ( const char code [ ] , bool experimental = true , const char filename [ ] = " test.cpp " ) {
2010-12-01 18:00:55 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
2015-10-07 18:33:57 +02:00
settings0 . inconclusive = true ;
settings0 . experimental = experimental ;
2010-12-01 18:00:55 +01:00
2008-12-18 22:28:57 +01:00
// Tokenize..
2015-10-07 18:33:57 +02:00
Tokenizer tokenizer ( & settings0 , this ) ;
2008-12-18 22:28:57 +01:00
std : : istringstream istr ( code ) ;
2012-04-16 20:02:52 +02:00
tokenizer . tokenize ( istr , filename ) ;
2008-12-18 22:28:57 +01:00
// Check for buffer overruns..
2015-05-03 15:00:47 +02:00
CheckBufferOverrun checkBufferOverrun ;
2016-07-27 17:28:43 +02:00
checkBufferOverrun . runChecks ( & tokenizer , & settings0 , this ) ;
2008-12-18 22:28:57 +01:00
}
2015-02-09 16:20:28 +01:00
void check ( const char code [ ] , const Settings & settings , const char filename [ ] = " test.cpp " ) {
2014-07-05 20:31:43 +02:00
Tokenizer tokenizer ( & settings , this ) ;
std : : istringstream istr ( code ) ;
tokenizer . tokenize ( istr , filename ) ;
// Clear the error buffer..
errout . str ( " " ) ;
// Check for buffer overruns..
CheckBufferOverrun checkBufferOverrun ( & tokenizer , & settings , this ) ;
2016-07-07 19:38:15 +02:00
checkBufferOverrun . runChecks ( & tokenizer , & settings , this ) ;
2014-07-05 20:31:43 +02:00
}
2019-01-12 15:45:25 +01:00
void run ( ) OVERRIDE {
2018-10-09 06:53:26 +02:00
LOAD_LIB_2 ( settings0 . library , " std.cfg " ) ;
2015-10-07 18:33:57 +02:00
settings0 . addEnabled ( " warning " ) ;
settings0 . addEnabled ( " style " ) ;
settings0 . addEnabled ( " portability " ) ;
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-06-05 04:50:06 +02:00
TEST_CASE ( sizeof3 ) ;
2009-01-05 16:49:57 +01:00
TEST_CASE ( array_index_1 ) ;
TEST_CASE ( array_index_2 ) ;
TEST_CASE ( array_index_3 ) ;
2019-10-21 07:11:22 +02:00
TEST_CASE ( array_index_4 ) ;
2009-01-05 16:49:57 +01:00
TEST_CASE ( array_index_6 ) ;
TEST_CASE ( array_index_7 ) ;
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
2019-03-19 13:16:22 +01: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 ) ;
2011-11-01 11:52:39 +01:00
TEST_CASE ( array_index_38 ) ; // ticket #3273
2011-12-06 20:53:56 +01:00
TEST_CASE ( array_index_39 ) ;
2011-12-17 21:35:12 +01:00
TEST_CASE ( array_index_40 ) ; // loop variable calculation, taking address
2011-12-18 08:12:42 +01:00
TEST_CASE ( array_index_41 ) ; // structs with the same name
2019-03-17 13:09:15 +01:00
TEST_CASE ( array_index_42 ) ;
2012-05-23 23:32:58 +02:00
TEST_CASE ( array_index_43 ) ; // struct with array
2012-07-19 09:44:06 +02:00
TEST_CASE ( array_index_44 ) ; // #3979
2012-09-22 16:19:19 +02:00
TEST_CASE ( array_index_45 ) ; // #4207 - calling function with variable number of parameters (...)
2013-06-25 06:37:51 +02:00
TEST_CASE ( array_index_46 ) ; // #4840 - two-statement for loop
2014-08-31 21:45:38 +02:00
TEST_CASE ( array_index_47 ) ; // #5849
2019-11-24 01:40:31 +01:00
TEST_CASE ( array_index_48 ) ; // #9478
2019-12-02 11:35:51 +01:00
TEST_CASE ( array_index_49 ) ; // #8653
2020-02-17 10:31:08 +01:00
TEST_CASE ( array_index_50 ) ;
2019-03-19 13:16:22 +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 ) ;
2012-09-17 13:18:19 +02:00
TEST_CASE ( array_index_negative2 ) ; // ticket #3063
2018-05-06 08:35:29 +02:00
TEST_CASE ( array_index_negative3 ) ;
2010-01-31 21:02:26 +01:00
TEST_CASE ( array_index_for_decr ) ;
2012-09-17 13:18:19 +02:00
TEST_CASE ( array_index_varnames ) ; // FP: struct member. #1576
2012-07-08 14:34:47 +02:00
TEST_CASE ( array_index_for_continue ) ; // for,continue
2012-09-17 13:18:19 +02:00
TEST_CASE ( array_index_for ) ; // FN: for,if
TEST_CASE ( array_index_for_neq ) ; // #2211: Using != in condition
TEST_CASE ( array_index_for_question ) ; // #2561: for, ?:
2012-06-23 09:23:14 +02:00
TEST_CASE ( array_index_for_andand_oror ) ; // FN: using && or || in the for loop condition
2012-09-23 17:15:39 +02:00
TEST_CASE ( array_index_for_varid0 ) ; // #4228: No varid for counter variable
2012-09-17 13:18:19 +02:00
TEST_CASE ( array_index_vla_for ) ; // #3221: access VLA inside for
TEST_CASE ( array_index_extern ) ; // FP when using 'extern'. #1684
TEST_CASE ( array_index_cast ) ; // FP after cast. #2841
2019-10-07 09:17:12 +02:00
TEST_CASE ( array_index_string_literal ) ;
2013-05-28 16:52:23 +02:00
TEST_CASE ( array_index_same_struct_and_var_name ) ; // #4751 - not handled well when struct name and var name is same
2014-01-16 19:23:14 +01:00
TEST_CASE ( array_index_valueflow ) ;
2015-11-08 17:21:32 +01:00
TEST_CASE ( array_index_valueflow_pointer ) ;
2014-12-24 14:03:52 +01:00
TEST_CASE ( array_index_function_parameter ) ;
2018-03-23 08:28:12 +01:00
TEST_CASE ( array_index_enum_array ) ; // #8439
2019-10-05 16:14:30 +02:00
TEST_CASE ( array_index_container ) ; // #9386
2020-06-05 18:06:03 +02:00
TEST_CASE ( array_index_two_for_loops ) ;
2009-01-05 16:49:57 +01:00
2012-12-22 09:23:34 +01:00
TEST_CASE ( buffer_overrun_2_struct ) ;
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 ) ;
2019-03-09 22:14:02 +01:00
// TODO strcat 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 ) ;
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-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-24 12:53:27 +02:00
TEST_CASE ( buffer_overrun_21 ) ;
2014-06-27 06:46:42 +02:00
TEST_CASE ( buffer_overrun_24 ) ; // index variable is changed in for-loop
2012-12-26 08:29:10 +01:00
TEST_CASE ( buffer_overrun_26 ) ; // #4432 (segmentation fault)
2012-12-28 11:15:18 +01:00
TEST_CASE ( buffer_overrun_27 ) ; // #4444 (segmentation fault)
2016-06-21 22:42:46 +02:00
TEST_CASE ( buffer_overrun_29 ) ; // #7083: false positive: typedef and initialization with strings
2018-03-23 08:28:12 +01:00
TEST_CASE ( buffer_overrun_30 ) ; // #6367
2019-03-19 21:06:37 +01:00
TEST_CASE ( buffer_overrun_31 ) ;
2019-03-17 20:12:02 +01:00
TEST_CASE ( buffer_overrun_errorpath ) ;
2019-10-07 09:17:12 +02:00
TEST_CASE ( buffer_overrun_bailoutIfSwitch ) ; // ticket #2378 : bailoutIfSwitch
2019-03-09 22:14:02 +01:00
// TODO TEST_CASE(buffer_overrun_function_array_argument);
// TODO alloca TEST_CASE(possible_buffer_overrun_1); // #3035
2015-01-30 20:27:48 +01:00
TEST_CASE ( buffer_overrun_readSizeFromCfg ) ;
2009-01-05 16:49:57 +01:00
2014-08-04 08:25:10 +02:00
TEST_CASE ( valueflow_string ) ; // using ValueFlow string values in checking
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
2019-03-31 09:00:52 +02:00
TEST_CASE ( pointer_out_of_bounds_1 ) ;
2019-03-09 22:14:02 +01:00
// TODO TEST_CASE(pointer_out_of_bounds_2);
2019-03-31 09:00:52 +02:00
TEST_CASE ( pointer_out_of_bounds_3 ) ;
2019-10-21 07:11:22 +02:00
TEST_CASE ( pointer_out_of_bounds_4 ) ;
2019-03-09 22:14:02 +01:00
// TODO TEST_CASE(pointer_out_of_bounds_sub);
2010-12-26 21:23:28 +01:00
2019-03-09 22:14:02 +01:00
// TODO TEST_CASE(strncat1);
// TODO TEST_CASE(strncat2);
// TODO TEST_CASE(strncat3);
2010-05-29 11:19:56 +02:00
2019-03-09 22:14:02 +01:00
// TODO TEST_CASE(strcat1);
// TODO TEST_CASE(strcat2);
// TODO TEST_CASE(strcat3);
2009-01-14 07:29:35 +01:00
2009-01-05 16:49:57 +01:00
TEST_CASE ( varid1 ) ;
2015-02-14 18:55:54 +01:00
TEST_CASE ( varid2 ) ; // ticket #4764
2009-02-12 20:11:52 +01:00
TEST_CASE ( assign1 ) ;
2009-03-16 18:11:09 +01:00
2019-03-17 13:09:15 +01:00
// TODO new TEST_CASE(alloc_new); // Buffer allocated with new
TEST_CASE ( alloc_malloc ) ; // Buffer allocated with malloc
TEST_CASE ( alloc_string ) ; // statically allocated buffer
2019-03-09 22:14:02 +01:00
// TODO TEST_CASE(alloc_alloca); // Buffer allocated with alloca
2009-03-25 07:25:10 +01:00
2019-03-09 22:14:02 +01:00
// TODO TEST_CASE(countSprintfLength);
2015-02-10 06:35:41 +01:00
TEST_CASE ( minsize_argvalue ) ;
2015-02-09 16:20:28 +01:00
TEST_CASE ( minsize_sizeof ) ;
2015-02-12 17:29:36 +01:00
TEST_CASE ( minsize_strlen ) ;
2015-02-10 06:44:19 +01:00
TEST_CASE ( minsize_mul ) ;
2009-11-15 16:44:30 +01:00
TEST_CASE ( unknownType ) ;
2009-12-18 17:26:15 +01:00
2019-03-12 21:15:26 +01:00
TEST_CASE ( terminateStrncpy1 ) ;
TEST_CASE ( terminateStrncpy2 ) ;
TEST_CASE ( terminateStrncpy3 ) ;
TEST_CASE ( terminateStrncpy4 ) ;
TEST_CASE ( recursive_long_time ) ;
2010-04-10 21:12:00 +02:00
2012-09-05 19:46:44 +02:00
TEST_CASE ( crash1 ) ; // Ticket #1587 - crash
2014-10-16 10:59:46 +02:00
TEST_CASE ( crash2 ) ; // Ticket #3034 - crash
TEST_CASE ( crash3 ) ; // Ticket #5426 - crash
2018-08-26 19:46:36 +02:00
TEST_CASE ( crash4 ) ; // Ticket #8679 - crash
2018-08-30 10:01:19 +02:00
TEST_CASE ( crash5 ) ; // Ticket #8644 - crash
2019-03-08 11:07:33 +01:00
TEST_CASE ( crash6 ) ; // Ticket #9024 - crash
2019-03-29 19:37:23 +01:00
TEST_CASE ( crash7 ) ; // Ticket #9073 - crash
2013-11-30 07:40:32 +01:00
2019-03-09 22:14:02 +01:00
// TODO TEST_CASE(insecureCmdLineArgs);
// TODO TEST_CASE(checkBufferAllocatedWithStrlen);
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
2011-08-04 11:15:14 +02:00
// Access array and then check if the used index is within bounds
2019-03-11 19:20:06 +01:00
TEST_CASE ( arrayIndexThenCheck ) ;
2011-09-05 21:59:41 +02:00
2019-03-09 22:14:02 +01:00
// TODO TEST_CASE(bufferNotZeroTerminated);
2014-02-01 22:38:29 +01:00
2019-03-09 22:14:02 +01:00
// TODO TEST_CASE(negativeMemoryAllocationSizeError) // #389
2015-05-03 15:00:47 +02:00
TEST_CASE ( negativeArraySize ) ;
2019-03-17 13:40:56 +01:00
2019-07-29 08:06:57 +02:00
TEST_CASE ( pointerAddition1 ) ;
2019-03-23 08:36:10 +01:00
2019-03-23 15:57:17 +01:00
TEST_CASE ( ctu_malloc ) ;
TEST_CASE ( ctu_array ) ;
TEST_CASE ( ctu_variable ) ;
2019-04-03 06:43:56 +02:00
TEST_CASE ( ctu_arithmetic ) ;
2019-05-31 11:16:04 +02:00
TEST_CASE ( objectIndex ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +01:00
void noerr4 ( ) {
2008-12-18 22:28:57 +01:00
// The memory isn't read or written and therefore there is no error.
2013-04-13 08:19:14 +02:00
check ( " static void f() { \n "
2009-01-05 16:49:57 +01:00
" char data[100]; \n "
2013-04-13 08:19:14 +02:00
" const char *p = data + 100; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +01: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 "
2013-04-13 08:19:14 +02:00
" snprintf(group, 32, \" %u \" , 0); \n "
2009-06-05 04:50:06 +02:00
" struct group *gr; \n "
2013-04-13 08:19:14 +02:00
" snprintf(group, 32, \" %u \" , gr->gr_gid); \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2009-06-05 04:50:06 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-01-28 06:31:26 +01:00
2014-11-20 14:20:09 +01:00
void array_index_1 ( ) {
2008-12-18 22:28:57 +01:00
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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'str[16]' accessed at index 16, which is 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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'str[16]' accessed at index 16, which is out of bounds. \n " , errout . str ( ) ) ;
2012-05-23 23:59:14 +02:00
// test stack array
check ( " int f() \n "
" { \n "
" int x[ 3 ] = { 0, 1, 2 }; \n "
" int y; \n "
" y = x[ 4 ]; \n "
" return y; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'x[3]' accessed at index 4, which is out of bounds. \n " , errout . str ( ) ) ;
2012-05-23 23:59:14 +02:00
check ( " int f() \n "
" { \n "
" int x[ 3 ] = { 0, 1, 2 }; \n "
" int y; \n "
" y = x[ 2 ]; \n "
" return y; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-05-23 23:59:14 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-03-09 22:14:02 +01:00
check ( " int x[5]; \n "
" int a = x[10]; \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (error) Array 'x[5]' accessed at index 10, which is out of bounds. \n " , errout . str ( ) ) ;
2019-03-12 06:46:38 +01:00
check ( " int x[5]; \n "
" int a = (x)[10]; \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (error) Array 'x[5]' accessed at index 10, which is out of bounds. \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +01:00
void array_index_2 ( ) {
2014-12-17 16:23:48 +01:00
check ( " void a(int i) \n " // valueflow
" { \n "
" char *str = new char[0x10]; \n "
" str[i] = 0; \n "
" } \n "
" void b() { a(16); } " ) ;
2018-12-18 14:36:49 +01:00
TODO_ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'str[16]' accessed at index 16, which is out of bounds. \n " , " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2019-03-09 22:14:02 +01:00
void array_index_4 ( ) {
check ( " char c = \" abc \" [4]; " ) ;
2019-10-21 07:11:22 +02:00
ASSERT_EQUALS ( " [test.cpp:1]: (error) Array ' \" abc \" [4]' accessed at index 4, which is out of bounds. \n " , errout . str ( ) ) ;
2019-03-09 22:14:02 +01:00
check ( " p = & \" abc \" [4]; " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " char c = \" \\ 0abc \" [2]; " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-10-21 07:11:22 +02:00
check ( " char c = L \" abc \" [4]; " ) ;
ASSERT_EQUALS ( " [test.cpp:1]: (error) Array 'L \" abc \" [4]' accessed at index 4, which is out of bounds. \n " , errout . str ( ) ) ;
2019-03-09 22:14:02 +01:00
}
2008-12-18 22:28:57 +01:00
2014-11-20 14:20:09 +01:00
void array_index_3 ( ) {
2015-07-30 22:42:45 +02:00
check ( " void f() \n "
" { \n "
" int val[50]; \n "
" int i, sum=0; \n "
" for (i = 0; i < 100; i++) \n "
" sum += val[i]; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (error) Array 'val[50]' accessed at index 99, which is out of bounds. \n " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" int val[50]; \n "
" int i, sum=0; \n "
" for (i = 1; i < 100; i++) \n "
" sum += val[i]; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (error) Array 'val[50]' accessed at index 99, which is out of bounds. \n " , errout . str ( ) ) ;
check ( " void f(int a) \n "
" { \n "
" int val[50]; \n "
" int i, sum=0; \n "
" for (i = a; i < 100; i++) \n "
" sum += val[i]; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (error) Array 'val[50]' accessed at index 99, which is out of bounds. \n " , errout . str ( ) ) ;
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 "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo(int argc) \n "
" { \n "
" char a[2]; \n "
" for (int i = 4; i < argc; i++){} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
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) Array 'a[10]' accessed at index 49, which is out of bounds. \n " , errout . str ( ) ) ;
2010-02-15 22:20:09 +01:00
}
2008-12-18 22:28:57 +01:00
2014-11-20 14:20:09 +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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:9]: (error) Array 'abc.str[10]' accessed at index 10, which is 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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:9]: (error) Array 'abc.str[10]' accessed at index 10, which is 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 "
2013-04-13 08:19:14 +02:00
" struct ABC* x = malloc(sizeof(struct ABC) + 10); \n "
2010-04-10 18:50:28 +02:00
" x->str[1] = 0; "
2013-03-14 09:45:47 +01:00
" } " ) ;
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 "
2013-04-13 13:56:22 +02:00
" struct ABC* x = malloc(sizeof(struct ABC) + 10); \n "
2011-09-09 13:46:06 +02:00
" x->str[1] = 0; "
2013-03-14 09:45:47 +01:00
" } " ) ;
2019-03-09 22:14:02 +01:00
TODO_ASSERT_EQUALS ( " error " , " " , 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 "
2013-04-13 13:56:22 +02:00
" struct ABC* x = malloc(sizeof(struct ABC) + 10); \n "
2011-09-04 20:39:24 +02:00
" x->str[10] = 0; "
2013-03-14 09:45:47 +01:00
" } " ) ;
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 "
2013-04-13 13:56:22 +02:00
" struct ABC* x = malloc(sizeof(struct ABC) + 10); \n "
2011-09-04 20:39:24 +02:00
" x->str[11] = 0; "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
TODO_ASSERT_EQUALS ( " [test.cpp:9]: (error) Array 'str[1]' accessed at index 11, which is out of bounds. \n " , " " , errout . str ( ) ) ;
2011-09-04 20:39:24 +02:00
2012-09-16 08:20:43 +02:00
// This is out of bounds if 'sizeof(ABC)' is 1 (No padding)
2011-09-10 16:14:32 +02:00
check ( " struct ABC \n "
" { \n "
" char str[1]; \n "
" }; \n "
" \n "
" static void f() \n "
" { \n "
2013-04-13 13:56:22 +02:00
" struct ABC* x = malloc(sizeof(ABC) + 10); \n "
2011-09-10 16:14:32 +02:00
" x->str[11] = 0; "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-09-16 08:20:43 +02:00
TODO_ASSERT_EQUALS ( " error " , " " , 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 "
2013-04-13 13:56:22 +02:00
" struct ABC* x = malloc(sizeof(struct ABC)); \n "
2011-09-04 20:39:24 +02:00
" x->str[1] = 0; "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
TODO_ASSERT_EQUALS ( " [test.cpp:9]: (error) Array 'str[1]' accessed at index 1, which is 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
2012-09-16 08:20:43 +02:00
// But only if 'sizeof(ABC)' is 1 (No padding)
2011-09-10 16:14:32 +02:00
check ( " struct ABC \n "
" { \n "
" char str[1]; \n "
" }; \n "
" \n "
" static void f() \n "
" { \n "
2013-04-13 13:56:22 +02:00
" struct ABC* x = malloc(sizeof(ABC)); \n "
2011-09-10 16:14:32 +02:00
" x->str[1] = 0; "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-09-16 08:20:43 +02:00
TODO_ASSERT_EQUALS ( " error " , " " , 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; "
2013-03-14 09:45:47 +01:00
" } " ) ;
2019-03-19 13:16:22 +01:00
ASSERT_EQUALS ( " [test.cpp:9]: (error) Array 'x.str[1]' accessed at index 1, which is 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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2014-06-26 17:36:20 +02:00
ASSERT_EQUALS ( " [test.cpp:10]: (error) Array 'f.str[10]' accessed at index 63, which is out of bounds. \n " , errout . str ( ) ) ;
2011-12-17 13:20:42 +01:00
check ( " struct AB { char a[NUM]; char b[NUM]; } \n "
" void f(struct AB *ab) { \n "
" ab->a[0] = 0; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2016-12-18 22:10:30 +01:00
check ( " union { char a[1]; int b; } ab; \n "
" void f() { \n "
" ab.a[2] = 0; \n "
" } " ) ;
2019-03-19 13:16:22 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Array 'ab.a[1]' accessed at index 2, which is out of bounds. \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2019-03-09 22:14:02 +01:00
ASSERT_EQUALS ( " [test.cpp:8]: (error) Array 'abc->str[10]' accessed at index 10, which is out of bounds. \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2019-03-09 22:14:02 +01:00
ASSERT_EQUALS ( " [test.cpp:13]: (error) Array 'abc->str[10]' accessed at index 10, which is out of bounds. \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:10]: (error) Array 'str[10]' accessed at index 10, which is 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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:10]: (error) Array 'str[10]' accessed at index 10, which is out of bounds. \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +01:00
void array_index_13 ( ) {
2009-06-29 23:42:46 +02:00
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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2009-06-29 23:42:46 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-08-02 09:55:42 +02:00
}
2014-11-20 14:20:09 +01:00
void array_index_14 ( ) {
2009-08-02 09:55:42 +02:00
check ( " void f() \n "
" { \n "
" int a[10]; \n "
" for (int i = 0; i < 10; i++) \n "
" a[i+10] = i; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'a[10]' accessed at index 19, which is out of bounds. \n " , errout . str ( ) ) ;
2009-08-02 09:55:42 +02:00
}
2014-11-20 14:20:09 +01:00
void array_index_15 ( ) {
2009-08-02 09:55:42 +02:00
check ( " void f() \n "
" { \n "
" int a[10]; \n "
" for (int i = 0; i < 10; i++) \n "
" a[10+i] = i; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'a[10]' accessed at index 19, which is out of bounds. \n " , errout . str ( ) ) ;
2009-08-02 09:55:42 +02:00
}
2014-11-20 14:20:09 +01:00
void array_index_16 ( ) {
2009-08-02 09:55:42 +02:00
check ( " void f() \n "
" { \n "
" int a[10]; \n "
" for (int i = 0; i < 10; i++) \n "
" a[i+1] = i; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'a[10]' accessed at index 10, which is out of bounds. \n " , errout . str ( ) ) ;
2009-08-02 09:55:42 +02:00
}
2014-11-20 14:20:09 +01:00
void array_index_17 ( ) {
2009-08-02 09:55:42 +02:00
check ( " void f() \n "
" { \n "
" int a[10]; \n "
" for (int i = 0; i < 10; i++) \n "
" a[i*2] = i; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'a[10]' accessed at index 18, which is 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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2009-09-30 14:51:33 +02:00
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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'a[12]' accessed at index 12, which is out of bounds. \n " , errout . str ( ) ) ;
2012-12-22 08:00:05 +01:00
check ( " void f() { \n " // #4398
" int a[2]; \n "
" for (int i = 0; i < 4; i+=2) \n "
" a[i] = 0; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2014-06-27 06:46:42 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'a[2]' accessed at index 2, which is out of bounds. \n " , errout . str ( ) ) ;
2012-12-22 08:00:05 +01:00
check ( " void f() { \n " // #4398
" int a[2]; \n "
" for (int i = 0; i < 4; i+=2) \n "
2013-04-13 13:56:22 +02:00
" do_stuff(a+i); \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-12-22 08:00:05 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-06-29 23:42:46 +02:00
}
2009-06-01 19:21:08 +02:00
2014-11-20 14:20:09 +01:00
void array_index_18 ( ) {
2009-10-01 10:33:53 +02:00
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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2009-10-01 10:33:53 +02:00
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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2009-10-01 10:33:53 +02:00
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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2009-10-01 10:33:53 +02:00
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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2009-10-01 10:33:53 +02:00
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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
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
}
2014-11-20 14:20:09 +01:00
void array_index_19 ( ) {
2009-10-06 13:50:27 +02:00
// "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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2009-10-06 13:50:27 +02:00
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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'a[2]' accessed at index 3, which is out of bounds. \n " , errout . str ( ) ) ;
2009-10-06 13:50:27 +02:00
}
2014-11-20 14:20:09 +01:00
void array_index_20 ( ) {
2009-10-29 15:04:23 +01:00
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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2009-10-29 15:04:23 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void array_index_21 ( ) {
2009-11-12 22:24:44 +01:00
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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2009-11-12 22:24:44 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void array_index_22 ( ) {
2012-07-07 20:21:08 +02:00
check ( " int main() { \n "
2009-11-12 22:31:13 +01:00
" size_t indices[2]; \n "
" int b = indices[2]; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Array 'indices[2]' accessed at index 2, which is out of bounds. \n " , errout . str ( ) ) ;
2009-11-12 22:31:13 +01:00
}
2014-11-20 14:20:09 +01:00
void array_index_23 ( ) {
2010-03-27 07:21:08 +01:00
check ( " void foo() \n "
" { \n "
" char c[10]; \n "
" c[1<<23]='a'; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'c[10]' accessed at index 8388608, which is out of bounds. \n " , errout . str ( ) ) ;
2010-03-27 07:21:08 +01:00
}
2014-11-20 14:20:09 +01:00
void array_index_24 ( ) {
2010-03-30 17:33:17 +02:00
// ticket #1492 and #1539
2019-03-16 18:29:02 +01:00
const std : : string charMaxPlusOne ( settings0 . defaultSign = = ' u ' ? " 256 " : " 128 " ) ;
2011-02-22 20:46:12 +01:00
check ( ( " void f(char n) { \n "
" int a[n]; \n " // n <= CHAR_MAX
" a[-1] = 0; \n " // negative index
2019-03-16 18:29:02 +01:00
" a[ " + charMaxPlusOne + " ] = 0; \n " // 128/256 > CHAR_MAX
2011-02-22 20:46:12 +01:00
" } \n " ) . c_str ( ) ) ;
2019-03-16 18:29:02 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Array 'a[ " + charMaxPlusOne + " ]' accessed at index -1, which is out of bounds. \n "
" [test.cpp:4]: (error) Array 'a[ " + charMaxPlusOne + " ]' accessed at index " + charMaxPlusOne + " , which 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
2013-03-14 09:45:47 +01:00
" } " ) ;
2019-03-09 22:14:02 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Array 'a[128]' accessed at index -1, which is out of bounds. \n "
2016-12-20 22:01:19 +01:00
" [test.cpp:4]: (error) Array 'a[128]' accessed at index 128, which 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
2013-03-14 09:45:47 +01:00
" } " ) ;
2019-03-09 22:14:02 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Array 'a[256]' accessed at index -1, which is out of bounds. \n "
2016-12-20 22:01:19 +01:00
" [test.cpp:4]: (error) Array 'a[256]' accessed at index 256, which 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
2013-03-14 09:45:47 +01:00
" } " ) ;
2019-03-09 22:14:02 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Array 'a[32768]' accessed at index -1, which is out of bounds. \n "
2016-12-20 22:01:19 +01:00
" [test.cpp:4]: (error) Array 'a[32768]' accessed at index 32768, which 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
2013-03-14 09:45:47 +01:00
" } " ) ;
2019-03-09 22:14:02 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Array 'a[65536]' accessed at index -1, which is out of bounds. \n "
2016-12-20 22:01:19 +01:00
" [test.cpp:4]: (error) Array 'a[65536]' accessed at index 65536, which 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
2013-03-14 09:45:47 +01:00
" } " ) ;
2019-03-09 22:14:02 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Array 'a[32768]' accessed at index -1, which is out of bounds. \n "
2016-12-20 22:01:19 +01:00
" [test.cpp:4]: (error) Array 'a[32768]' accessed at index 32768, which is out of bounds. \n " , errout . str ( ) ) ;
2010-03-30 17:33:17 +02:00
2012-03-27 19:40:39 +02:00
check ( " void f(int n) { \n "
" int a[n]; \n " // n <= INT_MAX
" a[-1] = 0; \n " // negative index
" } " ) ;
2019-03-09 22:14:02 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Array 'a[2147483648]' accessed at index -1, which is out of bounds. \n " , errout . str ( ) ) ;
2010-03-30 17:33:17 +02:00
2012-03-27 19:40:39 +02:00
check ( " void f(unsigned int n) { \n "
" int a[n]; \n " // n <= UINT_MAX
" a[-1] = 0; \n " // negative index
" } " ) ;
2019-03-09 22:14:02 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Array 'a[4294967296]' accessed at index -1, which is out of bounds. \n " , errout . str ( ) ) ;
2010-03-30 17:33:17 +02:00
2012-03-27 19:40:39 +02:00
check ( " void f(signed int n) { \n "
" int a[n]; \n " // n <= INT_MAX
" a[-1] = 0; \n " // negative index
" } " ) ;
2019-03-09 22:14:02 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Array 'a[2147483648]' accessed at index -1, which is out of bounds. \n " , errout . str ( ) ) ;
2010-03-28 15:56:13 +02:00
}
2015-07-30 22:42:45 +02:00
void array_index_25 ( ) { // #1536
2010-03-29 17:25:38 +02:00
check ( " void foo() \n "
" { \n "
" long l[SOME_SIZE]; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2010-03-29 17:25:38 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void array_index_26 ( ) {
2010-04-11 22:22:16 +02:00
check ( " void f() \n "
" { \n "
" int a[3]; \n "
" for (int i = 3; 0 <= i; i--) \n "
" a[i] = i; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2014-06-27 06:46:42 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'a[3]' accessed at index 3, which is out of bounds. \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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2010-04-11 22:22:16 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void array_index_27 ( ) {
2010-04-25 07:34:50 +02:00
check ( " void f() \n "
" { \n "
" int a[10]; \n "
" for (int i = 0; i < 10; i++) \n "
" a[i-1] = a[i]; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2019-03-09 22:14:02 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'a[10]' accessed at index -1, which is out of bounds. \n " , errout . str ( ) ) ;
2010-04-25 07:34:50 +02:00
}
2010-05-17 19:51:35 +02:00
2014-11-20 14:20:09 +01:00
void array_index_28 ( ) {
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 "
2013-04-13 13:56:22 +02:00
" int *ip = i + 1; \n "
2010-05-16 23:53:42 +02:00
" ip[-10] = 1; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02: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
2014-11-20 14:20:09 +01:00
void array_index_29 ( ) {
2010-06-06 16:20:50 +02:00
// ticket #1724
check ( " void f() \n "
" { \n "
" int iBuf[10]; "
2013-04-13 15:49:15 +02:00
" int *i = iBuf + 9; "
" int *ii = i + -5; "
2010-06-06 16:20:50 +02:00
" ii[10] = 0; "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02: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
}
2014-11-20 14:20:09 +01:00
void array_index_30 ( ) {
2010-10-11 20:52:14 +02:00
// ticket #2086 - unknown type
check ( " void f() { \n "
" UINT8 x[2]; \n "
" x[5] = 0; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Array 'x[2]' accessed at index 5, which is out of bounds. \n " , errout . str ( ) ) ;
2010-10-11 20:52:14 +02:00
}
2014-11-20 14:20:09 +01:00
void array_index_31 ( ) {
2010-10-23 08:49:03 +02:00
// 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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2010-10-23 08:49:03 +02:00
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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2019-03-09 22:14:02 +01:00
// TODO CTU ASSERT_EQUALS("[test.cpp:11] -> [test.cpp:6]: (error) Array 'obj.delay[3]' accessed at index 4, which is 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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2010-10-26 20:05:34 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-10-23 08:49:03 +02:00
}
2014-11-20 14:20:09 +01:00
void array_index_32 ( ) {
2011-01-31 13:46:51 +01:00
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 "
2013-03-19 09:18:58 +01:00
" }; " ) ;
2019-10-07 09:17:12 +02:00
ASSERT_EQUALS ( " [test.cpp:7]: (error) Array 'm_x[1]' accessed at index 1, which is out of bounds. \n " , errout . str ( ) ) ;
2011-01-31 13:46:51 +01:00
}
2014-11-20 14:20:09 +01:00
void array_index_33 ( ) {
2011-08-28 17:40:55 +02:00
check ( " void foo(char bar[][4]) { \n "
" baz(bar[5]); \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2011-08-28 17:40:55 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void array_index_34 ( ) { // ticket #3063
2011-09-03 01:35:09 +02:00
check ( " void foo() { \n "
" int y[2][2][2]; \n "
" y[0][2][0] = 0; \n "
" y[0][0][2] = 0; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2019-03-19 13:16:22 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Array 'y[2][2][2]' accessed at index y[0][2][0], which is out of bounds. \n "
" [test.cpp:4]: (error) Array 'y[2][2][2]' accessed at index y[0][0][2], which is 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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:9]: (error) Array 'test.a[10]' accessed at index 10, which is out of bounds. \n "
2019-03-19 13:16:22 +01:00
" [test.cpp:10]: (error) Array 'test.b[10][5]' accessed at index test.b[10][2], which is out of bounds. \n "
" [test.cpp:11]: (error) Array 'test.b[10][5]' accessed at index test.b[0][19], which is out of bounds. \n "
2017-04-30 14:22:18 +02:00
" [test.cpp:14]: (error) Array 'ptest->a[10]' accessed at index 10, which is out of bounds. \n "
2019-03-19 13:16:22 +01:00
" [test.cpp:15]: (error) Array 'ptest->b[10][5]' accessed at index ptest->b[10][2], which is out of bounds. \n "
" [test.cpp:16]: (error) Array 'ptest->b[10][5]' accessed at index ptest->b[0][19], which is 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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2019-03-19 13:16:22 +01:00
ASSERT_EQUALS ( " [test.cpp:8]: (error) Array 'test.a[10][5]' accessed at index test.a[9][5], which is out of bounds. \n "
" [test.cpp:9]: (error) Array 'test.a[10][5]' accessed at index test.a[0][50], which is out of bounds. \n "
" [test.cpp:12]: (error) Array 'ptest->a[10][5]' accessed at index ptest->a[9][5], which is out of bounds. \n "
" [test.cpp:13]: (error) Array 'ptest->a[10][5]' accessed at index ptest->a[0][50], which is out of bounds. \n " , errout . str ( ) ) ;
2011-09-05 01:54:57 +02:00
}
2014-11-20 14:20:09 +01:00
void array_index_35 ( ) { // ticket #2889
2011-09-05 01:54:57 +02:00
check ( " void f() { \n "
" struct Struct { unsigned m_Var[1]; } s; \n "
" s.m_Var[1] = 1; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2019-10-07 09:17:12 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Array 's.m_Var[1]' accessed at index 1, which is 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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2019-10-07 09:17:12 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 's.m_Var[1]' accessed at index 1, which is 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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2011-09-05 01:54:57 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-09-03 01:35:09 +02:00
}
2014-11-20 14:20:09 +01:00
void array_index_36 ( ) { // ticket #2960
2011-09-12 03:51:05 +02:00
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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:7]: (error) Array 'm_b[2]' accessed at index 2, which is out of bounds. \n "
" [test.cpp:7]: (error) Array 'rhs.m_b[2]' accessed at index 2, which is out of bounds. \n " , errout . str ( ) ) ;
2011-09-12 03:51:05 +02:00
}
2014-11-20 14:20:09 +01:00
void array_index_37 ( ) {
2011-09-23 03:23:40 +02:00
check ( " class Fred { \n "
" char x[X]; \n "
" Fred() { \n "
" for (unsigned int i = 0; i < 15; i++) \n "
" i; \n "
" } \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2011-09-23 03:23:40 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void array_index_38 ( ) { //ticket #3273
2013-04-13 13:13:13 +02:00
check ( " void aFunction() { \n "
" double aDoubleArray[ 10 ]; \n "
" unsigned int i; i = 0; \n "
2011-11-01 11:52:39 +01:00
" for( i = 0; i < 6; i++ ) \n "
" { \n "
2013-04-13 13:13:13 +02:00
" unsigned int j; j = 0; \n "
2011-11-01 11:52:39 +01:00
" for( j = 0; j < 5; j++ ) \n "
" { \n "
2013-04-13 13:13:13 +02:00
" unsigned int x; x = 0; \n "
2011-11-01 11:52:39 +01:00
" for( x = 0; x < 4; x++ ) \n "
" { \n "
" } \n "
" } \n "
" } \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2011-11-01 11:52:39 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void array_index_39 ( ) { // ticket 3387
2011-12-06 20:53:56 +01:00
check ( " void aFunction() \n "
" { \n "
" char a[10]; \n "
" a[10] = 0; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'a[10]' accessed at index 10, which is out of bounds. \n " , errout . str ( ) ) ;
2011-12-06 20:53:56 +01:00
}
2014-11-20 14:20:09 +01:00
void array_index_40 ( ) {
2011-12-17 21:35:12 +01:00
check ( " void f() { \n "
" char a[10]; \n "
" for (int i = 0; i < 10; ++i) \n "
" f2(&a[i + 1]); \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2011-12-17 21:35:12 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void array_index_41 ( ) {
2011-12-18 08:12:42 +01:00
// Don't generate false positives when structs have the same name
check ( " void a() { \n "
" struct Fred { char data[6]; } fred; \n "
" fred.data[4] = 0; \n " // <- no error
" } \n "
" \n "
" void b() { \n "
" struct Fred { char data[3]; } fred; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2011-12-18 08:12:42 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-12-18 16:43:46 +01:00
check ( " void a() { \n "
" struct Fred { char data[6]; } fred; \n "
" fred.data[4] = 0; \n " // <- no error
" } \n "
" \n "
" void b() { \n "
" struct Fred { char data[3]; } fred; \n "
" fred.data[4] = 0; \n " // <- error
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:8]: (error) Array 'fred.data[3]' accessed at index 4, which is out of bounds. \n " , errout . str ( ) ) ;
2011-12-18 08:12:42 +01:00
}
2014-11-20 14:20:09 +01:00
void array_index_42 ( ) { // ticket #3569
2012-01-31 16:13:28 +01:00
check ( " void f() \n "
" { \n "
2013-04-13 13:13:13 +02:00
" char *p; p = malloc(10); \n "
2012-01-31 16:13:28 +01:00
" p[10] = 7; \n "
" free(p); \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'p[10]' accessed at index 10, which is out of bounds. \n " , errout . str ( ) ) ;
2012-01-31 16:13:28 +01:00
check ( " void f() \n "
" { \n "
2013-04-13 13:13:13 +02:00
" char *p; p = malloc(10); \n "
2012-01-31 16:13:28 +01:00
" p[0] = 0; \n "
" p[9] = 9; \n "
" free(p); \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-01-31 16:13:28 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-01-31 16:25:57 +01:00
check ( " void f() \n "
" { \n "
2013-04-13 13:13:13 +02:00
" char *p; p = new char[10]; \n "
2012-01-31 16:25:57 +01:00
" p[0] = 0; \n "
" p[9] = 9; \n "
" delete [] p; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-01-31 16:25:57 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" char *p(new char[10]); \n "
" p[0] = 0; \n "
" p[9] = 9; \n "
" delete [] p; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-01-31 16:25:57 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
2012-01-31 16:48:05 +01:00
" char *p = NULL; "
2012-01-31 16:25:57 +01:00
" try{ \n "
2012-01-31 16:48:05 +01:00
" p = new char[10]; \n "
2012-01-31 16:25:57 +01:00
" } \n "
" catch(...){ \n "
" return; \n "
" } "
" p[0] = 0; \n "
" p[9] = 9; \n "
" delete [] p; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-01-31 16:25:57 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-01-31 16:13:28 +01:00
}
2014-11-20 14:20:09 +01:00
void array_index_43 ( ) { // #3838
2012-05-23 23:32:58 +02:00
2012-12-06 19:19:22 +01:00
check ( " int f( ) \n "
2012-05-23 23:32:58 +02:00
" { \n "
2012-09-17 13:18:19 +02:00
" struct { \n "
" int arr[ 3 ]; \n "
" } var[ 1 ]; \n "
2012-05-23 23:32:58 +02:00
" int y; \n "
" var[ 0 ].arr[ 0 ] = 0; \n "
" var[ 0 ].arr[ 1 ] = 1; \n "
" var[ 0 ].arr[ 2 ] = 2; \n "
2013-03-14 06:34:12 +01:00
" y = var[ 0 ].arr[ 3 ]; \n " // <-- array access out of bounds
2012-05-23 23:32:58 +02:00
" return y; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2019-03-09 22:14:02 +01:00
ASSERT_EQUALS ( " [test.cpp:10]: (error) Array 'var[0].arr[3]' accessed at index 3, which is out of bounds. \n " , errout . str ( ) ) ;
2012-05-23 23:32:58 +02:00
2012-12-06 19:19:22 +01:00
check ( " int f( ) \n "
2012-05-23 23:32:58 +02:00
" { \n "
2012-09-17 13:18:19 +02:00
" struct { \n "
" int arr[ 3 ]; \n "
" } var[ 1 ]; \n "
2013-03-14 06:34:12 +01:00
" int y=1; \n "
2012-05-23 23:32:58 +02:00
" var[ 0 ].arr[ 0 ] = 0; \n "
" var[ 0 ].arr[ 1 ] = 1; \n "
" var[ 0 ].arr[ 2 ] = 2; \n "
" y = var[ 0 ].arr[ 2 ]; \n "
" return y; \n "
2013-03-14 06:34:12 +01:00
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " int f( ){ \n "
" struct Struct{ \n "
" int arr[ 3 ]; \n "
" }; \n "
" int y; \n "
" Struct var; \n "
" var.arr[ 0 ] = 0; \n "
" var.arr[ 1 ] = 1; \n "
" var.arr[ 2 ] = 2; \n "
" var.arr[ 3 ] = 3; \n " // <-- array access out of bounds
" y=var.arr[ 3 ]; \n " // <-- array access out of bounds
" return y; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:10]: (error) Array 'var.arr[3]' accessed at index 3, which is out of bounds. \n "
" [test.cpp:11]: (error) Array 'var.arr[3]' accessed at index 3, which is out of bounds. \n " , errout . str ( ) ) ;
check ( " void f( ) { \n "
" struct S{ \n "
" int var[ 3 ]; \n "
" } ; \n "
" S var[2]; \n "
" var[0].var[ 0 ] = 0; \n "
" var[0].var[ 1 ] = 1; \n "
" var[0].var[ 2 ] = 2; \n "
" var[0].var[ 4 ] = 4; \n " // <-- array access out of bounds
" } " ) ;
2019-03-09 22:14:02 +01:00
ASSERT_EQUALS ( " [test.cpp:9]: (error) Array 'var[0].var[3]' accessed at index 4, which is out of bounds. \n " , errout . str ( ) ) ;
2013-03-14 06:34:12 +01:00
check ( " void f( ) { \n "
" struct S{ \n "
" int var[ 3 ]; \n "
" } ; \n "
" S var[2]; \n "
" var[0].var[ 0 ] = 0; \n "
" var[0].var[ 1 ] = 1; \n "
" var[0].var[ 2 ] = 2; \n "
" } " ) ;
2012-05-23 23:32:58 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2013-03-14 09:21:31 +01:00
2013-03-14 09:36:38 +01:00
// avoid FPs (modified examples taken from #3838)
2013-03-14 09:21:31 +01:00
check ( " struct AB { int a[10]; int b[10]; }; \n "
" int main() { \n "
" struct AB ab; \n "
2013-03-14 09:36:38 +01:00
" int * p = &ab.a[10]; \n "
2013-03-14 09:21:31 +01:00
" return 0; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2013-03-14 09:21:31 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2013-03-14 09:36:38 +01:00
2013-03-14 11:10:12 +01:00
check ( " struct AB { int a[10]; int b[10]; }; \n "
" int main() { \n "
" struct AB ab[1]; \n "
" int * p = &ab[0].a[10]; \n "
" return 0; \n "
" } " ) ;
2013-03-14 09:36:38 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2013-03-14 11:10:12 +01:00
check ( " struct AB { int a[10]; int b[10]; }; \n "
" int main() { \n "
" struct AB ab[1]; \n "
" int * p = &ab[10].a[0]; \n "
" return 0; \n "
" } " ) ;
2019-10-07 09:17:12 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'ab[1]' accessed at index 10, which is out of bounds. \n " , errout . str ( ) ) ;
2012-05-23 23:32:58 +02:00
}
2014-11-20 14:20:09 +01:00
void array_index_44 ( ) { // #3979 (false positive)
2012-07-19 09:44:06 +02:00
check ( " void f() \n "
" { \n "
" char buf[2]; \n "
" int i; \n "
" for (i = 2; --i >= 0; ) \n "
" { \n "
2012-09-05 19:46:44 +02:00
" buf[i] = 1; \n "
2012-07-19 09:44:06 +02:00
" } \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-08-12 17:06:54 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-07-19 09:44:06 +02:00
check ( " void f() \n "
" { \n "
2012-09-05 19:46:44 +02:00
" double buf[2]; \n "
2012-07-19 09:44:06 +02:00
" for (int i = 2; i--; ) \n "
" { \n "
2012-09-05 19:46:44 +02:00
" buf[i] = 2.; \n "
2012-07-19 09:44:06 +02:00
" } \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-08-12 17:06:54 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-07-19 09:44:06 +02:00
}
2014-11-20 14:20:09 +01:00
void array_index_45 ( ) { // #4207 - handling of function with variable number of parameters / unnamed arguments
2012-09-23 13:25:28 +02:00
// Variable number of arguments
2012-09-22 16:19:19 +02:00
check ( " void f(const char *format, ...) { \n "
" va_args args; \n "
" va_start(args, format); \n "
" } \n "
" void test() { \n "
" CHAR buffer[1024]; \n "
" f( \" %s \" , buffer); \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-09-22 16:19:19 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-09-23 13:25:28 +02:00
// Unnamed argument
check ( " void f(char *) { \n "
" dostuff(); \n "
" } \n "
" void test() { \n "
" char buffer[1024]; \n "
" f(buffer); \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-09-23 13:25:28 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-09-22 16:19:19 +02:00
}
2013-06-25 06:37:51 +02:00
// Two statement for-loop
2014-11-20 14:20:09 +01:00
void array_index_46 ( ) {
2013-06-25 06:37:51 +02:00
// #4840
check ( " void bufferAccessOutOfBounds2() { \n "
" char *buffer[]={ \" a \" , \" b \" , \" c \" }; \n "
" for(int i=3; i--;) { \n "
2017-05-18 21:52:31 +02:00
" printf( \" files(%i): %s \" , 3-i, buffer[3-i]); \n "
2013-06-25 06:37:51 +02:00
" } \n "
" } " ) ;
2014-06-27 06:46:42 +02:00
TODO_ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'buffer[3]' accessed at index 3, which is out of bounds. \n " , " " , errout . str ( ) ) ;
2013-06-25 06:37:51 +02:00
check ( " void f() { \n "
" int buffer[9]; \n "
" long int i; \n "
" for(i=10; i--;) { \n "
" buffer[i] = i; \n "
" } \n "
" } " ) ;
2014-06-27 06:46:42 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'buffer[9]' accessed at index 9, which is out of bounds. \n " , errout . str ( ) ) ;
2013-06-25 06:37:51 +02:00
// Correct access limits -> i from 9 to 0
check ( " void f() { \n "
" int buffer[10]; \n "
" for(unsigned long int i=10; i--;) { \n "
" buffer[i] = i; \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void array_index_47 ( ) {
2014-08-31 21:45:38 +02:00
// #5849
check ( " int s[4]; \n "
" void f() { \n "
" for (int i = 2; i < 0; i++) \n "
" s[i] = 5; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2019-11-24 01:40:31 +01:00
void array_index_48 ( ) {
// #9478
check ( " void test(void) \n "
" { \n "
" int array[4] = { 1,2,3,4 }; \n "
" for (int i = 1; i <= 4; i++) { \n "
" printf( \" %i \" , i); \n "
" array[i] = 0; \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (error) Array 'array[4]' accessed at index 4, which is out of bounds. \n " , errout . str ( ) ) ;
check ( " void test(void) \n "
" { \n "
" int array[4] = { 1,2,3,4 }; \n "
" for (int i = 1; i <= 4; i++) { \n "
" scanf( \" %i \" , &i); \n "
" array[i] = 0; \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2019-12-02 11:35:51 +01:00
void array_index_49 ( ) {
// #8653
check ( " void f() { \n "
" int i, k; \n "
" int arr[34] = {}; \n "
" i = 1; \n "
" for (k = 0; k < 34 && i < 34; k++) { \n "
" i++; \n "
" } \n "
" arr[k]; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2020-02-17 10:31:08 +01:00
void array_index_50 ( ) {
check ( " void f(const char * str) { \n "
" int len = strlen(str); \n "
" (void)str[len - 1]; \n "
" } \n "
" void g() { \n "
" f( \" 12345678 \" ); \n "
" f( \" 12345 \" ); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void array_index_multidim ( ) {
2009-10-28 21:42:54 +01:00
check ( " void f() \n "
" { \n "
" char a[2][2]; \n "
" a[1][1] = 'a'; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2009-10-28 21:42:54 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" char a[2][2][2]; \n "
" a[1][1][1] = 'a'; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2009-10-28 21:42:54 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" char a[2][2]; \n "
" a[2][1] = 'a'; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2019-03-19 13:16:22 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'a[2][2]' accessed at index a[2][1], which is 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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2019-03-19 13:16:22 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'a[2][2]' accessed at index a[1][2], which is 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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2019-03-19 13:16:22 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'a[2][2][2]' accessed at index a[2][1][1], which is 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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2019-03-19 13:16:22 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'a[2][2][2]' accessed at index a[1][2][1], which is 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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2019-03-19 13:16:22 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'a[2][2][2][2]' accessed at index a[1][2][1][1], which is out of bounds. \n " , errout . str ( ) ) ;
2010-04-23 22:04:49 +02:00
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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2019-03-19 13:16:22 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'a[2][2][2]' accessed at index a[1][1][2], which is 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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2019-03-19 13:16:22 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'a[10][10][10]' accessed at index a[6][12][2], which is out of bounds. \n " , errout . str ( ) ) ;
2010-04-23 21:56:35 +02:00
2013-04-13 13:13:13 +02:00
check ( " void f() { \n "
" char a[10][10][10]; \n "
" a[6][40][10] = 'a'; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2019-03-19 13:16:22 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Array 'a[10][10][10]' accessed at index a[6][40][10], which is out of bounds. \n " , errout . str ( ) ) ;
2010-04-23 22:04:49 +02:00
2013-04-13 13:13:13 +02:00
check ( " void f() { \n "
" char a[1][1][1]; \n "
" a[2][2][2] = 'a'; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2019-03-19 13:16:22 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Array 'a[1][1][1]' accessed at index a[2][2][2], which is out of bounds. \n " , errout . str ( ) ) ;
2010-04-23 22:04:49 +02:00
2013-04-13 15:49:15 +02:00
check ( " void f() { \n "
" char a[6][6][6]; \n "
" a[6][6][2] = 'a'; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2019-03-19 13:16:22 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Array 'a[6][6][6]' accessed at index a[6][6][2], which is out of bounds. \n " , errout . str ( ) ) ;
2010-04-23 21:56:35 +02:00
2014-05-03 18:12:06 +02:00
check ( " void f() { \n "
" int a[2][2]; \n "
" p = &a[2][0]; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2011-08-05 13:08:48 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-08-29 19:00:09 +02:00
check ( " void draw_quad(float z) { \n "
" int i; \n "
" float (*vertices)[2][4]; \n "
" vertices[0][0][0] = z; \n "
" vertices[0][0][1] = z; \n "
" vertices[1][0][0] = z; \n "
" vertices[1][0][1] = z; \n "
" vertices[2][0][0] = z; \n "
" vertices[2][0][1] = z; \n "
" vertices[3][0][0] = z; \n "
" vertices[3][0][1] = z; \n "
" for (i = 0; i < 4; i++) { \n "
" vertices[i][0][2] = z; \n "
" vertices[i][0][3] = 1.0; \n "
" vertices[i][1][0] = 2.0; \n "
" vertices[i][1][1] = 3.0; \n "
" vertices[i][1][2] = 4.0; \n "
" vertices[i][1][3] = 5.0; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2016-12-20 22:01:19 +01:00
{
check ( " int foo() { \n "
" const size_t A = 4; \n "
" const size_t B = 2; \n "
" extern int stuff[A][B]; \n "
" return stuff[0][1]; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// TODO: better handling of VLAs in symboldatabase. should be
// possible to use ValueFlow values.
check ( " int foo() { \n "
" const size_t A = 4; \n "
" const size_t B = 2; \n "
" extern int stuff[A][B]; \n "
" return stuff[0][1]; \n "
" } " ) ;
TODO_ASSERT_EQUALS ( " error " , " " , errout . str ( ) ) ;
}
2009-10-28 21:42:54 +01:00
}
2014-11-20 14:20:09 +01:00
void array_index_switch_in_for ( ) {
2009-11-25 21:40:51 +01:00
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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2009-11-25 21:40:51 +01:00
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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
TODO_ASSERT_EQUALS ( " [test.cpp:12]: (error) Array index out of bounds. \n " , " " , errout . str ( ) ) ;
2009-11-25 21:40:51 +01:00
}
2014-11-20 14:20:09 +01:00
void array_index_for_in_for ( ) {
2011-03-08 19:49:56 +01:00
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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2011-03-08 19:49:56 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void array_index_calculation ( ) {
2010-01-03 15:49:17 +01:00
// #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 "
2013-04-13 13:56:22 +02:00
" data[i/2] = 0; \n "
2010-01-03 15:49:17 +01:00
" } \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'data[8]' accessed at index 17, which is 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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'arr[5]' accessed at index 11, which is out of bounds. \n " , errout . str ( ) ) ;
2010-01-03 15:49:17 +01:00
}
2014-11-20 14:20:09 +01: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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2019-03-09 22:14:02 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'data[8]' accessed at index -1, which 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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2019-10-07 09:17:12 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'data[8][4]' accessed at index data[*][-1], which 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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2010-04-20 16:43:51 +02:00
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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2010-05-19 19:23:09 +02:00
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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2010-07-14 12:24:07 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-01-11 21:18:07 +01:00
}
2014-11-20 14:20:09 +01:00
void array_index_negative2 ( ) { // ticket #3063
2011-09-03 03:07:29 +02:00
check ( " struct TEST { char a[10]; }; \n "
" void foo() { \n "
" TEST test; \n "
" test.a[-1] = 3; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2014-03-25 20:37:32 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'test.a[10]' accessed at index -1, which is out of bounds. \n " , errout . str ( ) ) ;
2011-09-03 03:07:29 +02:00
}
2018-05-06 08:35:29 +02:00
void array_index_negative3 ( ) {
2018-05-06 09:50:53 +02:00
check ( " int f(int i) { \n "
" int p[2] = {0, 0}; \n "
" if(i >= 2) \n "
" return 0; \n "
" else if(i == 0) \n "
" return 0; \n "
" return p[i - 1]; \n "
" } \n "
" void g(int i) { \n "
" if( i == 0 ) \n "
" return f(i); \n "
" } " ) ;
2018-05-06 08:35:29 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void array_index_for_decr ( ) {
2010-01-31 21:02:26 +01:00
check ( " void f() \n "
" { \n "
" char data[8]; \n "
" for (int i = 10; i > 0; --i) { \n "
" data[i] = 0; \n "
" } \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2014-06-27 06:46:42 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'data[8]' accessed at index 10, which is out of bounds. \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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2010-04-01 21:35:36 +02:00
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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2019-03-09 22:14:02 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'val[5]' accessed at index -9994, which is out of bounds. \n "
" [test.cpp:5]: (error) Array 'val[5]' accessed at index -9995, which is out of bounds. \n " , errout . str ( ) ) ;
2010-01-31 21:02:26 +01:00
}
2010-04-08 19:57:38 +02:00
2014-11-20 14:20:09 +01:00
void array_index_varnames ( ) {
2010-04-08 19:57:38 +02:00
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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2010-04-08 19:57:38 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void array_index_for_andand_oror ( ) { // #3907 - using && or ||
2012-06-23 09:23:14 +02:00
check ( " void f() { \n "
" char data[2]; \n "
" int x; \n "
" for (x = 0; x < 10 && y; x++) { \n "
" data[x] = 0; \n "
" } "
" } " ) ;
2014-06-27 06:46:42 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'data[2]' accessed at index 9, which is out of bounds. \n " , errout . str ( ) ) ;
2012-06-23 09:23:14 +02:00
check ( " void f() { \n "
" char data[2]; \n "
" int x; \n "
" for (x = 0; x < 10 || y; x++) { \n "
" data[x] = 0; \n "
" } "
" } " ) ;
2014-06-27 06:46:42 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'data[2]' accessed at index 9, which is out of bounds. \n " , errout . str ( ) ) ;
2012-06-23 09:23:14 +02:00
check ( " void f() { \n "
" char data[2]; \n "
" int x; \n "
" for (x = 0; x <= 10 && y; x++) { \n "
" data[x] = 0; \n "
" } "
" } " ) ;
2014-06-27 06:46:42 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'data[2]' accessed at index 10, which is out of bounds. \n " , errout . str ( ) ) ;
2012-06-23 09:23:14 +02:00
check ( " void f() { \n "
" char data[2]; \n "
" int x; \n "
" for (x = 0; y && x <= 10; x++) { \n "
" data[x] = 0; \n "
" } "
" } " ) ;
2014-06-27 06:46:42 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'data[2]' accessed at index 10, which is out of bounds. \n " , errout . str ( ) ) ;
2012-06-23 09:23:14 +02:00
}
2010-04-08 19:57:38 +02:00
2014-11-20 14:20:09 +01:00
void array_index_for_continue ( ) {
2012-07-09 11:11:05 +02:00
// #3913
2012-07-08 14:34:47 +02:00
check ( " void f() { \n "
" int a[2]; \n "
" for (int i = 0; i < 2; ++i) { \n "
" if (i == 0) { \n "
" continue; \n "
" } \n "
" a[i - 1] = 0; \n "
" } \n "
2015-07-25 14:17:55 +02:00
" } " , true ) ;
2012-07-08 14:34:47 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" int a[2]; \n "
" for (int i = 0; i < 2; ++i) { \n "
" if (somecondition) { \n "
" continue; \n "
" } \n "
" a[i - 1] = 0; \n "
" } \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2019-03-09 22:14:02 +01:00
ASSERT_EQUALS ( " [test.cpp:7]: (error) Array 'a[2]' accessed at index -1, which is out of bounds. \n " , errout . str ( ) ) ;
2012-07-08 14:34:47 +02:00
}
2014-11-20 14:20:09 +01:00
void array_index_for ( ) {
2010-12-28 20:46:31 +01:00
// 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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2014-06-27 06:46:42 +02:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) Array 'a[10]' accessed at index 19, which is out of bounds. \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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2010-12-31 17:43:38 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-06-16 17:44:51 +02:00
// Ticket #3893 - start value out of bounds
check ( " void f() { \n "
" int a[10]; \n "
" for (int i = 10; somecondition; dosomething) { \n "
" a[i] = 0; \n "
" } \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2014-06-27 06:46:42 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'a[10]' accessed at index 10, which is out of bounds. \n " , errout . str ( ) ) ;
2010-12-28 20:46:31 +01:00
}
2014-11-20 14:20:09 +01:00
void array_index_for_neq ( ) {
2011-01-09 18:51:28 +01:00
// 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 "
" } " ) ;
2014-06-27 06:46:42 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'a[5]' accessed at index 9, which is out of bounds. \n " ,
2014-03-17 18:43:47 +01:00
errout . str ( ) ) ;
2011-01-09 18:51:28 +01:00
}
2010-12-19 10:39:43 +01:00
2014-11-20 14:20:09 +01:00
void array_index_for_question ( ) {
2011-02-12 11:31:10 +01:00
// 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 ( ) ) ;
2012-11-30 09:01:15 +01:00
check ( " void f() { \n "
" int a[10]; \n "
" for (int i = 0; i != 10; ++i) { \n "
" some_condition ? 0 : a[i-1]; \n "
" } \n "
" } " ) ;
2015-02-01 14:01:55 +01:00
TODO_ASSERT_EQUALS ( " [test.cpp:4]: (error) Array index -1 is out of bounds. \n " , " " , errout . str ( ) ) ;
2012-11-30 09:01:15 +01:00
check ( " void f() { \n "
" int a[10]; \n "
" for (int i = 0; i != 10; ++i) { \n "
" i==0 ? 0 : a[i-1]; \n "
" a[i-1] = 0; \n "
" } \n "
" } " ) ;
2019-03-09 22:14:02 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'a[10]' accessed at index -1, which is out of bounds. \n " , errout . str ( ) ) ;
2011-02-12 11:31:10 +01:00
}
2011-10-29 20:27:50 +02:00
2014-11-20 14:20:09 +01:00
void array_index_for_varid0 ( ) { // #4228: No varid for counter variable
2012-09-23 17:15:39 +02:00
check ( " void f() { \n "
" char a[10]; \n "
" for (i=0; i<10; i++); \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-09-23 17:15:39 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void array_index_vla_for ( ) {
2011-10-29 20:26:24 +02:00
// #3221 - access VLA inside for
check ( " void f(int len) { \n "
" char a[len]; \n "
" for (int i=0; i<7; ++i) { \n "
" a[0] = 0; \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2011-02-12 11:31:10 +01:00
2014-11-20 14:20:09 +01:00
void array_index_extern ( ) {
2011-05-07 11:34:48 +02:00
// Ticket #1684. FP when using 'extern'.
check ( " extern char arr[15]; \n "
" char arr[15] = \" abc \" ; " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void array_index_cast ( ) {
2011-06-29 18:44:05 +02:00
// 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 "
" } " ) ;
2019-03-09 22:14:02 +01:00
// TODO CTU ASSERT_EQUALS("[test.cpp:6] -> [test.cpp:2]: (error) Array 'x[2]' accessed at index 4, which is out of bounds.\n", errout.str());
2011-06-29 18:44:05 +02:00
}
2014-11-20 14:20:09 +01:00
void array_index_string_literal ( ) {
2013-04-13 11:01:19 +02:00
check ( " void f() { \n "
2011-12-01 04:17:09 +01:00
" const char *str = \" abc \" ; \n "
2013-04-13 11:01:19 +02:00
" bar(str[10]); \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2013-04-13 11:01:19 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Array 'str[4]' accessed at index 10, which is out of bounds. \n " , errout . str ( ) ) ;
2011-12-01 04:17:09 +01:00
check ( " void f() \n "
" { \n "
" const char *str = \" abc \" ; \n "
" bar(str[4]); \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'str[4]' accessed at index 4, which is out of bounds. \n " , errout . str ( ) ) ;
2011-12-01 04:17:09 +01:00
check ( " void f() \n "
" { \n "
" const char *str = \" abc \" ; \n "
" bar(str[3]); \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2011-12-01 04:17:09 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" const char *str = \" a \t c \" ; \n "
" bar(str[4]); \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'str[4]' accessed at index 4, which is out of bounds. \n " , errout . str ( ) ) ;
2011-12-01 04:17:09 +01:00
2015-11-30 16:34:59 +01:00
check ( " void f() { \n " // #6973
" const char *name = \" \" ; \n "
" if ( name[0] == 'U' ? name[1] : 0) {} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2016-07-07 19:38:15 +02:00
check ( " int main(int argc, char **argv) { \n "
" char str[6] = \" \\ 0 \" ; \n "
" unsigned short port = 65535; \n "
" snprintf(str, sizeof(str), \" %hu \" , port); \n "
" } " , settings0 , " test.c " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-12-01 04:17:09 +01:00
}
2014-11-20 14:20:09 +01:00
void array_index_same_struct_and_var_name ( ) {
2013-05-28 16:52:23 +02:00
// don't throw internal error
check ( " struct tt { \n "
2013-12-31 17:51:56 +01:00
" char name[21]; \n "
2013-05-28 16:52:23 +02:00
" } ; \n "
" void doswitch(struct tt *x) \n "
" { \n "
" struct tt *tt=x; \n "
2013-12-31 17:51:56 +01:00
" tt->name; \n "
2013-05-28 16:52:23 +02:00
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// detect error
check ( " struct tt { \n "
2013-12-31 17:51:56 +01:00
" char name[21]; \n "
2013-05-28 16:52:23 +02:00
" } ; \n "
" void doswitch(struct tt *x) \n "
" { \n "
" struct tt *tt=x; \n "
2013-12-31 17:51:56 +01:00
" tt->name[22] = 123; \n "
2013-05-28 16:52:23 +02:00
" } " ) ;
2019-03-09 22:14:02 +01:00
ASSERT_EQUALS ( " [test.cpp:7]: (error) Array 'tt->name[21]' accessed at index 22, which is out of bounds. \n " , errout . str ( ) ) ;
2013-05-28 16:52:23 +02:00
}
2014-11-20 14:20:09 +01:00
void array_index_valueflow ( ) {
2014-01-17 18:07:05 +01:00
check ( " void f(int i) { \n "
" char str[3]; \n "
" str[i] = 0; \n "
" if (i==10) {} \n "
" } " ) ;
2019-03-09 22:14:02 +01:00
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:3]: (warning) Either the condition 'i==10' is redundant or the array 'str[3]' is accessed at index 10, which is out of bounds. \n " , errout . str ( ) ) ;
2015-07-29 19:54:57 +02:00
check ( " void f(int i) { \n "
" char str[3]; \n "
" str[i] = 0; \n "
" switch (i) { \n "
" case 10: break; \n "
" } \n "
" } " ) ;
2019-03-09 22:14:02 +01:00
ASSERT_EQUALS ( " [test.cpp:5] -> [test.cpp:3]: (warning) Either the switch case 'case 10' is redundant or the array 'str[3]' is accessed at index 10, which is out of bounds. \n " , errout . str ( ) ) ;
2014-01-20 22:26:55 +01:00
check ( " void f() { \n "
" char str[3]; \n "
" str[((unsigned char)3) - 1] = 0; \n "
2015-07-25 14:17:55 +02:00
" } " , false , " test.cpp " ) ;
2014-01-20 22:26:55 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-01-28 16:55:10 +01:00
check ( " void f() { \n " // #5416 FP
" char *str[3]; \n "
" do_something(&str[0][5]); \n "
2015-07-25 14:17:55 +02:00
" } " , false , " test.cpp " ) ;
2014-01-28 16:55:10 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-08-19 07:03:00 +02:00
check ( " class X { static const int x[100]; }; \n " // #6070
2019-03-13 06:39:09 +01:00
" const int X::x[100] = {0}; " ) ;
2014-08-19 07:03:00 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-10-21 22:56:53 +02:00
check ( " namespace { class X { static const int x[100]; }; \n " // #6232
2019-03-13 06:39:09 +01:00
" const int X::x[100] = {0}; } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " class ActorSprite { static ImageSet * targetCursorImages[2][10]; }; \n "
" ImageSet *ActorSprite::targetCursorImages[2][10]; \n " ) ;
2014-10-21 22:56:53 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-11-07 18:12:01 +01:00
2015-11-08 17:21:32 +01:00
}
void array_index_valueflow_pointer ( ) {
2015-11-07 18:12:01 +01:00
check ( " void f() { \n "
" int a[10]; \n "
" int *p = a; \n "
" p[20] = 0; \n "
" } " ) ;
2019-03-09 22:14:02 +01:00
// TODO pointer ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (error) Array 'a[10]' accessed at index 20, which is out of bounds.\n", errout.str());
2015-11-08 09:30:23 +01:00
2015-11-09 10:30:39 +01:00
{
// address of
check ( " void f() { \n "
" int a[10]; \n "
" int *p = a; \n "
" p[10] = 0; \n "
" } " ) ;
2019-03-09 22:14:02 +01:00
// TODO pointer ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (error) Array 'a[10]' accessed at index 10, which is out of bounds.\n", errout.str());
2015-11-09 10:30:39 +01:00
check ( " void f() { \n "
" int a[10]; \n "
" int *p = a; \n "
" dostuff(&p[10]); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2015-11-08 09:30:23 +01:00
check ( " void f() { \n "
2015-11-08 17:21:32 +01:00
" int a[X]; \n " // unknown size
2015-11-08 09:30:23 +01:00
" int *p = a; \n "
" p[20] = 0; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-11-08 17:21:32 +01:00
check ( " void f() { \n "
" int a[2]; \n "
" char *p = (char *)a; \n " // cast
" p[4] = 0; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-01-16 19:23:14 +01:00
}
2014-12-24 14:03:52 +01:00
void array_index_function_parameter ( ) {
check ( " void f(char a[10]) { \n "
" a[20] = 0; \n " // <- cppcheck warn here even though it's not a definite access out of bounds
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (error) Array 'a[10]' accessed at index 20, which is out of bounds. \n " , errout . str ( ) ) ;
check ( " void f(char a[10]) { \n " // #6353 - reassign 'a'
" a += 4; \n "
" a[-1] = 0; \n "
" } " ) ;
2019-03-09 22:14:02 +01:00
// TODO ASSERT_EQUALS("", errout.str());
2014-12-24 14:03:52 +01:00
}
2018-03-23 08:28:12 +01:00
void array_index_enum_array ( ) { // #8439
check ( " enum E : unsigned int { e1, e2 }; \n "
" void f() { \n "
" E arrE[] = { e1, e2 }; \n "
" arrE[sizeof(arrE)] = e1; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'arrE[2]' accessed at index 8, which is out of bounds. \n " , errout . str ( ) ) ;
}
2019-10-05 16:14:30 +02:00
void array_index_container ( ) { // #9386
check ( " constexpr int blockLen = 10; \n "
" void foo(std::array<uint8_t, blockLen * 2>& a) { \n "
" a[2] = 2; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2020-06-05 18:06:03 +02:00
void array_index_two_for_loops ( ) {
check ( " bool b(); \n "
" void f() \n "
" { \n "
" int val[50]; \n "
" int i, sum=0; \n "
" for (i = 1; b() && i < 50; i++) \n "
" sum += val[i]; \n "
" if (i < 50) \n "
" sum -= val[i]; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " bool b(); \n "
" void f() \n "
" { \n "
" int val[50]; \n "
" int i, sum=0; \n "
" for (i = 1; b() && i < 50; i++) \n "
" sum += val[i]; \n "
" for (; i < 50;) { \n "
" sum -= val[i]; \n "
" break; \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " bool b(); \n "
" void f() \n "
" { \n "
" int val[50]; \n "
" int i, sum=0; \n "
" for (i = 1; b() && i < 50; i++) \n "
" sum += val[i]; \n "
" for (; i < 50; i++) \n "
" sum -= val[i]; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void buffer_overrun_2_struct ( ) {
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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2019-03-09 22:14:02 +01:00
ASSERT_EQUALS ( " [test.cpp:8]: (error) Buffer is accessed 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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:9]: (error) Buffer is accessed 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(struct ABC &abc) \n "
" { \n "
" strcpy( abc.str, \" abcdef \" ); \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:8]: (error) Buffer is accessed 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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:7]: (error) Buffer is accessed 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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2019-03-09 22:14:02 +01:00
ASSERT_EQUALS ( " [test.cpp:8]: (error) Buffer is accessed out of bounds: abc->str \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +01:00
void buffer_overrun_3 ( ) {
2009-02-11 17:12:29 +01:00
check ( " int a[10]; \n "
" \n "
" void foo() \n "
" { \n "
" int i; \n "
" for (i = 0; i <= 10; ++i) \n "
" a[i] = 0; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2014-06-27 06:46:42 +02:00
ASSERT_EQUALS ( " [test.cpp:7]: (error) Array 'a[10]' accessed at index 10, which is out of bounds. \n " , errout . str ( ) ) ;
2009-02-11 17:12:29 +01:00
}
2014-11-20 14:20:09 +01:00
void buffer_overrun_4 ( ) {
2009-06-01 19:21:08 +02:00
check ( " void foo() \n "
" { \n "
" const char *p[2]; \n "
" for (int i = 0; i < 8; ++i) \n "
" p[i] = 0; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2014-06-27 06:46:42 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'p[2]' accessed at index 7, which is out of bounds. \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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2009-06-02 18:56:53 +02:00
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 "
2012-12-22 09:23:34 +01:00
" f1(s,20); \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
TODO_ASSERT_EQUALS ( " [test.cpp:8] -> [test.cpp:3]: (error) Buffer is accessed 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
2014-11-20 14:20:09 +01:00
void buffer_overrun_5 ( ) {
2009-08-26 19:17:32 +02:00
check ( " void f() \n "
" { \n "
" char n[5]; \n "
" sprintf(n, \" d \" ); \n "
" printf( \" hello! \" ); \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2009-08-26 19:17:32 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-02-11 17:12:29 +01:00
2014-11-20 14:20:09 +01:00
void buffer_overrun_6 ( ) {
2009-08-30 13:44:23 +02:00
check ( " void f() \n "
" { \n "
" char n[5]; \n "
" strcat(n, \" abc \" ); \n "
" strcat(n, \" def \" ); \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Buffer is accessed out of bounds: n \n " , errout . str ( ) ) ;
2009-08-30 13:44:23 +02:00
}
2009-02-11 17:12:29 +01:00
2014-11-20 14:20:09 +01:00
void buffer_overrun_7 ( ) {
2009-09-26 17:58:14 +02:00
// ticket #731
check ( " void f() \n "
" { \n "
" char a[2]; \n "
" strcpy(a, \" a \\ 0 \" ); \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2009-09-26 17:58:14 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void buffer_overrun_8 ( ) {
2009-09-27 16:09:41 +02:00
// ticket #714
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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2009-09-27 16:09:41 +02:00
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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2009-09-27 16:09:41 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void buffer_overrun_9 ( ) {
2009-09-27 17:07:54 +02:00
// 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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2009-09-27 17:07:54 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void buffer_overrun_10 ( ) {
2009-09-27 17:50:59 +02:00
// 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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2009-09-27 17:50:59 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void buffer_overrun_11 ( ) {
2009-10-05 22:19:44 +02:00
check ( " void f() \n "
" { \n "
" char a[4]; \n "
" for (float i=0; i<10.0;i=i+0.1) \n "
" { \n "
" } \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2009-10-05 22:19:44 +02:00
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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2009-10-05 22:19:44 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-09-27 16:09:41 +02:00
2014-11-20 14:20:09 +01:00
void buffer_overrun_15 ( ) { // ticket #1787
2010-06-13 07:17:50 +02:00
check ( " class A : public B { \n "
2015-02-12 17:29:36 +01:00
" char val[2]; \n "
2010-06-13 07:17:50 +02:00
" void f(int i, int ii); \n "
" }; \n "
" void A::f(int i, int ii) \n "
" { \n "
2015-02-12 17:29:36 +01:00
" strcpy(val, \" ab \" ) ; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2015-02-12 17:29:36 +01:00
ASSERT_EQUALS ( " [test.cpp:7]: (error) Buffer is accessed out of bounds: val \n " , errout . str ( ) ) ;
2010-06-13 07:17:50 +02:00
}
2014-11-20 14:20:09 +01: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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2010-10-12 19:35:20 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-10-13 18:06:50 +02:00
2012-09-05 19:46:44 +02:00
check ( " void f() { \n " // ticket #2093
2010-10-13 18:06:50 +02:00
" gchar x[3]; \n "
" strcpy(x, \" 12 \" ); \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2010-10-13 18:06:50 +02:00
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 "
2013-04-13 11:01:19 +02:00
" std::memcpy(b, a, 10); \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2010-10-13 20:57:59 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-10-12 19:35:20 +02:00
}
2014-11-20 14:20:09 +01:00
void buffer_overrun_18 ( ) { // ticket #2576
2011-02-12 18:34:12 +01:00
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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2011-02-12 18:34:12 +01:00
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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:8]: (error) Array 'b[7]' accessed at index 7, which is out of bounds. \n " , errout . str ( ) ) ;
2011-02-12 18:34:12 +01:00
}
2014-11-20 14:20:09 +01:00
void buffer_overrun_19 ( ) { // #2597 - class member with unknown type
2011-02-20 21:24:57 +01:00
check ( " class A { \n "
" public: \n "
" u8 buf[10]; \n "
" A(); "
" }; \n "
" \n "
" A::A() { \n "
" memset(buf, 0, 10); \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2011-02-20 21:24:57 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void buffer_overrun_21 ( ) {
2011-08-24 12:53:27 +02:00
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 " ) ;
2014-06-27 06:46:42 +02:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) Array 'dst[4]' accessed at index 4, which is out of bounds. \n " , errout . str ( ) ) ;
2011-08-24 12:53:27 +02:00
}
2014-11-20 14:20:09 +01:00
void buffer_overrun_24 ( ) { // index variable is changed in for-loop
2014-06-27 06:46:42 +02:00
// ticket #4106
2012-09-01 19:17:28 +02:00
check ( " void main() { \n "
" int array[] = {1,2}; \n "
" int x = 0; \n "
2012-12-06 19:19:22 +01:00
" for( int i = 0; i<6; ) { \n "
2012-09-01 19:17:28 +02:00
" x += array[i]; \n "
" i++; } \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2014-06-27 06:46:42 +02:00
TODO_ASSERT_EQUALS ( " error " , " " , errout . str ( ) ) ;
2012-09-01 19:17:28 +02:00
2014-06-27 06:46:42 +02:00
// ticket #4096
2012-09-01 19:17:28 +02:00
check ( " void main() { \n "
" int array[] = {1,2}; \n "
" int x = 0; \n "
2012-12-06 19:19:22 +01:00
" for( int i = 0; i<6; ) { \n "
2012-09-01 19:17:28 +02:00
" x += array[i++]; \n "
2014-06-27 06:46:42 +02:00
" } \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2014-06-27 06:46:42 +02:00
TODO_ASSERT_EQUALS ( " error " , " " , errout . str ( ) ) ;
2012-09-01 19:17:28 +02:00
}
2014-11-20 14:20:09 +01:00
void buffer_overrun_26 ( ) { // ticket #4432 (segmentation fault)
2012-12-26 08:29:10 +01:00
check ( " extern int split(); \n "
" void regress() { \n "
" char inbuf[1000]; \n "
" char *f[10]; \n "
" split(inbuf, f, 10, \" \t \t \" ); \n "
2012-12-26 12:50:59 +01:00
" } " ) ;
2012-12-26 08:29:10 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void buffer_overrun_27 ( ) { // ticket #4444 (segmentation fault)
2012-12-28 11:15:18 +01:00
check ( " void abc(struct foobar[5]); \n "
" void main() { \n "
" struct foobar x[5]; \n "
" abc(x); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2016-06-21 22:42:46 +02:00
// #7083: false positive: typedef and initialization with strings
void buffer_overrun_29 ( ) {
check ( " typedef char testChar[10]; \n "
" int main(){ \n "
" testChar tc1 = \" \" ; \n "
" tc1[5]='a'; \n "
" } \n "
) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2018-03-23 08:28:12 +01:00
// #6367
void buffer_overrun_30 ( ) {
check ( " struct S { int m[9]; }; \n "
" int f(S * s) { \n "
" return s->m[sizeof(s->m)]; \n "
" } \n "
) ;
2019-03-09 22:14:02 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Array 's->m[9]' accessed at index 36, which is out of bounds. \n " , errout . str ( ) ) ;
2018-03-23 08:28:12 +01:00
}
2019-03-19 21:06:37 +01:00
void buffer_overrun_31 ( ) {
check ( " void f(WhereInfo *pWInfo, int *aiCur) { \n "
" memcpy(aiCur, pWInfo->aiCurOnePass, sizeof(int)*2); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2019-03-17 20:12:02 +01:00
void buffer_overrun_errorpath ( ) {
setMultiline ( ) ;
settings0 . templateLocation = " {file}:{line}:note:{info} " ;
check ( " void f() { \n "
" char *p = malloc(10); \n "
" memset(p, 0, 20); \n "
" } " ) ;
ASSERT_EQUALS ( " test.cpp:3:error:Buffer is accessed out of bounds: p \n "
" test.cpp:2:note:Assign p, buffer with size 10 \n "
" test.cpp:3:note:Buffer overrun \n " , errout . str ( ) ) ;
}
2018-03-23 08:28:12 +01:00
2014-11-20 14:20:09 +01:00
void buffer_overrun_bailoutIfSwitch ( ) {
2010-12-31 18:07:46 +01:00
// 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); "
" } " ) ;
2019-10-07 09:17:12 +02:00
TODO_ASSERT_EQUALS ( " [test.cpp:8] -> [test.cpp:3]: (error) Array 'a[10]' accessed at index 100, which is out of bounds. \n " , " " , errout . str ( ) ) ;
2010-12-31 18:07:46 +01:00
}
2014-11-20 14:20:09 +01:00
void buffer_overrun_function_array_argument ( ) {
2012-12-22 09:23:34 +01:00
check ( " void f(char a[10]); \n "
" void g() { \n "
" char a[2]; \n "
" f(a); \n "
" } " ) ;
2013-02-16 09:52:27 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (warning) The array 'a' is too small, the function 'f' expects a bigger one. \n " , errout . str ( ) ) ;
2012-12-22 09:23:34 +01:00
check ( " void f(float a[10][20]); \n "
" void g() { \n "
" float a[2][3]; \n "
" f(a); \n "
" } " ) ;
2013-02-16 09:52:27 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (warning) The array 'a' is too small, the function 'f' expects a bigger one. \n " , errout . str ( ) ) ;
2012-12-22 09:23:34 +01:00
check ( " void f(char a[20]); \n "
" void g() { \n "
" int a[2]; \n "
" f(a); \n "
" } " ) ;
2013-02-16 09:52:27 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (warning) The array 'a' is too small, the function 'f' expects a bigger one. \n " , errout . str ( ) ) ;
2012-12-22 09:23:34 +01:00
check ( " void f(char a[20]); \n "
" void g() { \n "
" int a[5]; \n "
" f(a); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-03-07 19:51:13 +01:00
check ( " void f(int a[]) { \n "
" switch (2) { \n "
" case 1: \n "
" a[1] = 1; \n "
" } \n "
" } \n "
" int a[1]; \n "
" f(a); \n "
" " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-08-29 11:14:13 +02:00
check ( " void CreateLeafTex(unsigned char buf[256][2048][4]); \n "
" void foo() { \n "
" unsigned char(* tree)[2048][4] = new unsigned char[256][2048][4]; \n "
" CreateLeafTex(tree); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-12-22 09:23:34 +01:00
}
2014-11-20 14:20:09 +01:00
void possible_buffer_overrun_1 ( ) { // #3035
2011-08-21 20:44:55 +02:00
check ( " void foo() { \n "
2013-04-13 08:19:14 +02:00
" char * data = alloca(50); \n "
2011-08-21 20:44:55 +02:00
" char src[100]; \n "
2013-04-13 08:19:14 +02:00
" memset(src, 'C', 99); \n "
" src[99] = ' \\ 0'; \n "
2011-08-21 20:44:55 +02:00
" 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 "
2013-04-13 08:19:14 +02:00
" char * data = alloca(100); \n "
2011-08-21 20:44:55 +02:00
" char src[100]; \n "
2013-04-13 08:19:14 +02:00
" memset(src, 'C', 99); \n "
" src[99] = ' \\ 0'; \n "
2011-08-21 20:44:55 +02:00
" strcat(data, src); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo(char src[100]) { \n "
2013-04-13 08:19:14 +02:00
" char * data = alloca(50); \n "
2011-08-21 20:44:55 +02:00
" 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 "
2013-04-13 08:19:14 +02:00
" char * data = alloca(100); \n "
2011-08-21 20:44:55 +02:00
" strcat(data, src); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-08-21 21:18:41 +02:00
check ( " void foo() { \n "
2013-04-13 08:19:14 +02:00
" char * data = alloca(50); \n "
2011-08-21 21:18:41 +02:00
" char src[100]; \n "
2013-04-13 08:19:14 +02:00
" memset(src, 'C', 99); \n "
" src[99] = ' \\ 0'; \n "
2011-08-21 21:18:41 +02:00
" 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 "
2013-04-13 08:19:14 +02:00
" char * data = alloca(100); \n "
2011-08-21 21:18:41 +02:00
" char src[100]; \n "
2013-04-13 08:19:14 +02:00
" memset(src, 'C', 99); \n "
" src[99] = ' \\ 0'; \n "
2011-08-21 21:18:41 +02:00
" strcpy(data, src); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo(char src[100]) { \n "
2013-04-13 08:19:14 +02:00
" char * data = alloca(50); \n "
2011-08-21 21:18:41 +02:00
" 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 "
2013-04-13 08:19:14 +02:00
" char * data = alloca(100); \n "
2011-08-21 21:18:41 +02:00
" strcpy(data, src); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-08-21 20:44:55 +02:00
}
2015-01-30 20:27:48 +01:00
void buffer_overrun_readSizeFromCfg ( ) {
2015-02-14 17:30:08 +01:00
Settings settings ;
const char xmldata [ ] = " <?xml version= \" 1.0 \" ?> \n "
" <def> \n "
" <podtype name= \" u8 \" sign= \" u \" size= \" 1 \" /> \n "
" <function name= \" mystrcpy \" > \n "
" <noreturn>false</noreturn> \n "
" <arg nr= \" 1 \" > \n "
" <minsize type= \" strlen \" arg= \" 2 \" /> \n "
" </arg> \n "
" <arg nr= \" 2 \" /> \n "
" </function> \n "
" </def> " ;
tinyxml2 : : XMLDocument doc ;
doc . Parse ( xmldata , sizeof ( xmldata ) ) ;
settings . library . load ( doc ) ;
2015-01-30 20:27:48 +01:00
// Attempt to get size from Cfg files, no false positives if size is not specified
2015-02-14 17:30:08 +01:00
check ( " void f() { \n "
" u8 str[256]; \n "
" mystrcpy(str, \" abcd \" ); \n "
" } " , settings ) ;
2015-01-30 20:27:48 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-02-14 17:30:08 +01:00
check ( " void f() { \n "
" u8 str[2]; \n "
" mystrcpy(str, \" abcd \" ); \n "
" } " , settings ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Buffer is accessed out of bounds: str \n " , errout . str ( ) ) ;
2015-01-30 20:27:48 +01:00
// The same for structs, where the message comes from a different check
2015-02-14 17:30:08 +01:00
check ( " void f() { \n "
" struct { u8 str[256]; } ms; \n "
" mystrcpy(ms.str, \" abcd \" ); \n "
" } " , settings ) ;
2015-01-30 20:27:48 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-02-14 17:30:08 +01:00
check ( " void f() { \n "
" struct { u8 str[2]; } ms; \n "
" mystrcpy(ms.str, \" abcd \" ); \n "
" } " , settings ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Buffer is accessed out of bounds: ms.str \n " , errout . str ( ) ) ;
2015-01-30 20:27:48 +01:00
}
2014-11-20 14:20:09 +01:00
void valueflow_string ( ) { // using ValueFlow string values in checking
2014-08-04 08:25:10 +02:00
check ( " char f() { \n "
" const char *x = s; \n "
" if (cond) x = \" abcde \" ; \n "
" return x[20]; \n " // <- array index out of bounds when x is "abcde"
" } " ) ;
2019-10-07 09:17:12 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'x[6]' accessed at index 20, which is out of bounds. \n " , errout . str ( ) ) ;
2014-08-04 08:25:10 +02:00
}
2014-11-20 14:20:09 +01:00
void pointer_out_of_bounds_1 ( ) {
2010-12-26 21:23:28 +01:00
check ( " void f() { \n "
" char a[10]; \n "
" char *p = a + 100; \n "
" } " ) ;
2014-12-25 14:31:46 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (portability) Undefined behaviour, pointer arithmetic 'a+100' is out of bounds. \n " , errout . str ( ) ) ;
2014-12-22 09:38:00 +01:00
check ( " void f() { \n "
" char a[10]; \n "
" return a + 100; \n "
" } " ) ;
2014-12-25 14:31:46 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (portability) Undefined behaviour, pointer arithmetic 'a+100' is out of bounds. \n " , errout . str ( ) ) ;
2014-12-23 16:16:14 +01:00
2014-12-26 09:12:00 +01:00
check ( " void f(int i) { \n "
" char x[10]; \n "
" if (i == 123) {} \n "
" dostuff(x+i); \n "
" } " ) ;
2019-03-31 09:00:52 +02:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (portability) Undefined behaviour, when 'i' is 123 the pointer arithmetic 'x+i' is out of bounds. \n " , errout . str ( ) ) ;
2014-12-26 09:12:00 +01:00
2020-03-02 17:01:27 +01:00
check ( " void f(int i) { \n "
2020-03-03 20:38:30 +01:00
" char x[10]; \n "
" if (i == -1) {} \n "
" dostuff(x+i); \n "
" } " ) ;
2020-03-02 17:01:27 +01:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (portability) Undefined behaviour, when 'i' is -1 the pointer arithmetic 'x+i' is out of bounds. \n " , errout . str ( ) ) ;
2014-12-23 16:16:14 +01:00
check ( " void f() { \n " // #6350 - fp when there is cast of buffer
" wchar_t buf[64]; \n "
" p = (unsigned char *) buf + sizeof (buf); \n "
2015-07-25 14:17:55 +02:00
" } " , false , " 6350.c " ) ;
2014-12-23 16:16:14 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-01-21 20:05:35 +01:00
check ( " int f() { \n "
" const char d[] = \" 0123456789 \" ; \n "
" char *cp = d + 3; \n "
" return cp - d; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-12-26 21:23:28 +01:00
}
2014-11-20 14:20:09 +01:00
void pointer_out_of_bounds_2 ( ) {
2011-01-01 20:56:21 +01:00
check ( " void f() { \n "
" char *p = malloc(10); \n "
" p += 100; \n "
" free(p); "
" } " ) ;
2014-12-25 14:31:46 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (portability) Undefined behaviour, pointer arithmetic 'p+100' is out of bounds. \n " , errout . str ( ) ) ;
2011-01-01 20:56:21 +01:00
check ( " void f() { \n "
" char *p = malloc(10); \n "
" p += 10; \n "
" *p = 0; \n "
" free(p); "
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) p is out of bounds. \n " , errout . str ( ) ) ;
2011-01-01 20:56:21 +01:00
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 "
2013-04-13 08:19:14 +02:00
" p = p - 1; \n "
2011-01-01 20:56:21 +01:00
" *p = 0; \n "
" free(p); "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2018-01-27 15:39:27 +01:00
void pointer_out_of_bounds_3 ( ) {
check ( " struct S { int a[10]; }; \n "
" void f(struct S *s) { \n "
" char *p = s->a + 100; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (portability) Undefined behaviour, pointer arithmetic 's->a+100' is out of bounds. \n " , errout . str ( ) ) ;
}
2019-10-21 07:11:22 +02:00
void pointer_out_of_bounds_4 ( ) {
check ( " const char* f() { \n "
" g( \" Hello \" + 6); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " const char* f() { \n "
" g( \" Hello \" + 7); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (portability) Undefined behaviour, pointer arithmetic ' \" Hello \" +7' is out of bounds. \n " , errout . str ( ) ) ;
check ( " const char16_t* f() { \n "
" g(u \" Hello \" + 6); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " const char16_t* f() { \n "
" g(u \" Hello \" + 7); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (portability) Undefined behaviour, pointer arithmetic 'u \" Hello \" +7' is out of bounds. \n " , errout . str ( ) ) ;
}
2014-12-22 09:38:00 +01:00
void pointer_out_of_bounds_sub ( ) {
check ( " void f() { \n "
" char x[10]; \n "
" return x-1; \n "
" } " ) ;
2014-12-25 14:31:46 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (portability) Undefined behaviour, pointer arithmetic 'x-1' is out of bounds. \n " , errout . str ( ) ) ;
2014-12-26 09:12:00 +01:00
check ( " void f(int i) { \n "
" char x[10]; \n "
" if (i == 123) {} \n "
" dostuff(x-i); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (portability) Undefined behaviour, when 'i' is 123 the pointer arithmetic 'x-i' is out of bounds. \n " , errout . str ( ) ) ;
check ( " void f(int i) { \n "
" char x[10]; \n "
" if (i == -20) {} \n "
" dostuff(x-i); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (portability) Undefined behaviour, when 'i' is -20 the pointer arithmetic 'x-i' is out of bounds. \n " , errout . str ( ) ) ;
2014-12-22 09:38:00 +01:00
}
2014-11-20 14:20:09 +01:00
void strncat1 ( ) {
2015-02-14 18:55:54 +01:00
check ( " void f(char *a, char *b) { \n "
" char str[16]; \n "
" strncpy(str, a, 10); \n "
" strncat(str, b, 10); \n "
" } " ) ;
2014-07-05 20:31:43 +02: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
}
2014-11-20 14:20:09 +01:00
void strncat2 ( ) {
2015-02-14 18:55:54 +01:00
check ( " void f(char *a) { \n "
" char str[5]; \n "
" strncat(str, a, 5); \n "
" } " ) ;
2014-07-05 20:31:43 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (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
}
2014-11-20 14:20:09 +01:00
void strncat3 ( ) {
2015-02-14 18:55:54 +01:00
check ( " void f(char *a) { \n "
" char str[5]; \n "
" strncat(str, \" foobar \" , 5); \n "
" } " ) ;
2013-03-14 18:18:48 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (warning) Dangerous usage of strncat - 3rd parameter is the maximum number of characters to append. \n " , errout . str ( ) ) ;
}
2010-05-29 07:51:28 +02:00
2014-11-20 14:20:09 +01:00
void strcat1 ( ) {
2015-02-14 18:55:54 +01:00
check ( " struct Foo { char a[4]; }; \n "
" void f() { \n "
" struct Foo x; \n "
" strcat(x.a, \" aa \" ); \n "
" strcat(x.a, \" aa \" ); \n "
" } " ) ;
2014-07-05 20:31:43 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Buffer is accessed out of bounds. \n " , errout . str ( ) ) ;
2010-05-29 07:51:28 +02:00
}
2010-05-29 11:19:56 +02:00
2014-11-20 14:20:09 +01:00
void strcat2 ( ) {
2015-02-14 18:55:54 +01:00
check ( " struct Foo { char a[5]; }; \n "
" void f() { \n "
" struct Foo x; \n "
" strcat(x.a, \" aa \" ); \n "
" strcat(x.a, \" aa \" ); \n "
" } " ) ;
2010-05-29 07:51:28 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-02-20 21:00:49 +01:00
2014-11-20 14:20:09 +01:00
void strcat3 ( ) {
2015-02-14 18:55:54 +01:00
check ( " void f() { \n "
" INT str[10]; \n "
" strcat(str, \" aa \" ); \n "
" } " ) ;
2010-12-18 10:54:36 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2015-02-14 18:55:54 +01:00
void varid2 ( ) { // #4764
2013-08-09 23:40:00 +02:00
check ( " struct foo { \n "
" void bar() { return; } \n "
" type<> member[1]; \n "
" }; " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-02-12 20:11:52 +01:00
2014-11-20 14:20:09 +01:00
void assign1 ( ) {
2009-02-12 20:11:52 +01:00
check ( " char str[3] = {'a', 'b', 'c'}; \n "
" \n "
" void foo() \n "
" { \n "
" str[3] = 0; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'str[3]' accessed at index 3, which is out of bounds. \n " , errout . str ( ) ) ;
2009-02-12 20:11:52 +01:00
}
2009-03-16 18:11:09 +01:00
2015-02-14 16:29:05 +01:00
void alloc_new ( ) {
2009-03-16 18:11:09 +01:00
check ( " void foo() \n "
" { \n "
2013-04-13 15:49:15 +02:00
" char *s; s = new char[10]; \n "
2009-03-16 18:11:09 +01:00
" s[10] = 0; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 's[10]' accessed at index 10, which is out of bounds. \n " , errout . str ( ) ) ;
2010-08-04 20:38:52 +02:00
// 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 "
2013-04-13 15:49:15 +02:00
" char *s; s = new int[10]; \n "
2010-08-04 20:38:52 +02:00
" return s[10]; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 's[10]' accessed at index 10, which is 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 "
2013-04-13 15:49:15 +02:00
" Fred *f; f = new Fred; \n "
2011-09-11 20:00:53 +02:00
" return f->c[10]; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2019-03-09 22:14:02 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'f->c[10]' accessed at index 10, which is out of bounds. \n " , errout . str ( ) ) ;
2009-03-16 18:11:09 +01:00
2014-12-20 18:50:08 +01:00
check ( " static const size_t MAX_SIZE = UNAVAILABLE_TO_CPPCHECK; \n "
" struct Thing { char data[MAX_SIZE]; }; \n "
" char f4(const Thing& t) { return !t.data[0]; } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-02-14 16:29:05 +01:00
check ( " void foo() { \n "
" char * buf; buf = new char[8]; \n "
" buf[7] = 0; \n "
" delete [] buf; \n "
" buf = new char[9]; \n "
" buf[8] = 0; \n "
" delete [] buf; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2010-02-10 22:11:08 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-02-14 16:29:05 +01:00
check ( " void foo() { \n "
" char * buf; buf = new char[8]; \n "
" buf[7] = 0; \n "
" delete [] buf; \n "
" buf = new char[9]; \n "
" buf[9] = 0; \n "
" delete [] buf; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2015-02-14 16:29:05 +01:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) Array 'buf[9]' accessed at index 9, which is out of bounds. \n " , errout . str ( ) ) ;
2016-07-08 20:53:08 +02:00
check ( " void foo() \n "
" { \n "
" enum E { Size = 10 }; \n "
" char *s; s = new char[Size]; \n "
" s[Size] = 0; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 's[10]' accessed at index 10, which is out of bounds. \n " , errout . str ( ) ) ;
check ( " void foo() \n "
" { \n "
" enum E { }; \n "
" E *e; e = new E[10]; \n "
2017-04-04 10:45:08 +02:00
" e[10] = 0; \n "
2016-07-08 20:53:08 +02:00
" } " ) ;
2017-04-04 10:45:08 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'e[10]' accessed at index 10, which is out of bounds. \n " , 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
2015-02-14 16:29:05 +01:00
void alloc_malloc ( ) {
2010-04-10 07:57:29 +02:00
check ( " void foo() \n "
" { \n "
2013-04-13 15:49:15 +02:00
" char *s; s = malloc(10); \n "
2010-04-10 07:57:29 +02:00
" s[10] = 0; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 's[10]' accessed at index 10, which is out of bounds. \n " , errout . str ( ) ) ;
2010-04-10 07:57:29 +02:00
// ticket #842
check ( " void f() { \n "
" int *tab4 = malloc(20 * sizeof(int)); \n "
" tab4[20] = 0; \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Array 'tab4[20]' accessed at index 20, which is out of bounds. \n " , errout . str ( ) ) ;
2010-04-10 07:57:29 +02:00
2017-12-31 14:58:26 +01:00
// ticket #1478
check ( " void foo() { \n "
" char *p = malloc(10); \n "
" free(p); \n "
" p = malloc(10); \n "
" p[10] = 0; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (error) Array 'p[10]' accessed at index 10, which is out of bounds. \n " , errout . str ( ) ) ;
2010-04-10 07:57:29 +02:00
// ticket #1134
check ( " void f() { \n "
" int *x, i; \n "
" x = malloc(10 * sizeof(int)); \n "
" x[10] = 0; \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'x[10]' accessed at index 10, which is out of bounds. \n " , errout . str ( ) ) ;
2015-02-14 16:29:05 +01:00
check ( " void f() { \n "
" int *tab4; 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 "
2015-07-25 14:17:55 +02:00
" } " ) ;
2015-02-14 16:29:05 +01:00
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 "
2015-07-25 14:17:55 +02:00
" } " ) ;
2015-02-14 16:29:05 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2016-07-08 20:53:08 +02:00
check ( " void f() { \n "
" enum E { Size = 20 }; \n "
" E *tab4 = malloc(Size * 4); \n "
" tab4[Size] = 0; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'tab4[20]' accessed at index 20, which is out of bounds. \n " , errout . str ( ) ) ;
check ( " void f() { \n "
" enum E { Size = 20 }; \n "
" E *tab4 = malloc(4 * Size); \n "
" tab4[Size] = 0; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'tab4[20]' accessed at index 20, which is out of bounds. \n " , errout . str ( ) ) ;
check ( " void f() { \n "
" enum E { }; \n "
" E *tab4 = malloc(20 * sizeof(E)); \n "
" tab4[20] = 0; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 'tab4[20]' accessed at index 20, which is out of bounds. \n " , errout . str ( ) ) ;
2018-08-31 18:25:08 +02:00
check ( " void f() { \n " // #8721
" unsigned char **cache = malloc(32); \n "
" cache[i] = malloc(65536); \n "
" cache[i][0xFFFF] = 0; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-04-10 07:57:29 +02:00
}
2009-03-25 07:25:10 +01:00
2010-10-10 09:15:18 +02:00
// statically allocated buffer
2015-02-14 16:29:05 +01:00
void alloc_string ( ) {
2010-10-10 09:15:18 +02:00
check ( " void foo() \n "
" { \n "
" const char *s = \" 123 \" ; \n "
" s[10] = 0; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 's[4]' accessed at index 10, which is 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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 's[1]' accessed at index 10, which is 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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2011-08-08 18:22:15 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-10-09 06:53:26 +02:00
check ( " void foo() \n " // #7718
" { \n "
" std::string s = \" 123 \" ; \n "
" s.resize(100); \n "
" s[10] = 0; \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
2015-02-14 16:29:05 +01:00
void alloc_alloca ( ) {
2011-07-17 09:35:51 +02:00
check ( " void foo() \n "
" { \n "
2013-04-13 15:49:15 +02:00
" char *s = alloca(10); \n "
2011-07-17 09:35:51 +02:00
" s[10] = 0; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Array 's[10]' accessed at index 10, which is out of bounds. \n " , errout . str ( ) ) ;
2011-07-17 09:35:51 +02:00
}
2019-03-09 22:14:02 +01:00
/*
void countSprintfLength ( ) const {
std : : list < const Token * > unknownParameter ( 1 , nullptr ) ;
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 ) ) ;
ASSERT_EQUALS ( 2 , CheckBufferOverrun : : countSprintfLength ( " f%s " , unknownParameter ) ) ;
ASSERT_EQUALS ( 1 , CheckBufferOverrun : : countSprintfLength ( " %-s " , unknownParameter ) ) ;
ASSERT_EQUALS ( 6 , CheckBufferOverrun : : countSprintfLength ( " %-5s " , unknownParameter ) ) ;
ASSERT_EQUALS ( 2 , CheckBufferOverrun : : countSprintfLength ( " \\ \" " , unknownParameter ) ) ;
ASSERT_EQUALS ( 7 , CheckBufferOverrun : : countSprintfLength ( " Hello \\ 0Text " , unknownParameter ) ) ;
ASSERT_EQUALS ( 1 , CheckBufferOverrun : : countSprintfLength ( " \\ 0 " , unknownParameter ) ) ;
ASSERT_EQUALS ( 2 , CheckBufferOverrun : : countSprintfLength ( " %% " , unknownParameter ) ) ;
ASSERT_EQUALS ( 3 , CheckBufferOverrun : : countSprintfLength ( " %d%d " , unknownParameter ) ) ;
ASSERT_EQUALS ( 3 , CheckBufferOverrun : : countSprintfLength ( " \\ \\ a%s \\ 0a " , unknownParameter ) ) ;
ASSERT_EQUALS ( 10 , CheckBufferOverrun : : countSprintfLength ( " \\ \\ \\ \\ Hello%d \\ 0Text \\ \\ \\ \\ " , unknownParameter ) ) ;
ASSERT_EQUALS ( 4 , CheckBufferOverrun : : countSprintfLength ( " %%%%%d " , unknownParameter ) ) ;
Token strTok ;
std : : list < const Token * > stringAsParameter ( 1 , & strTok ) ;
strTok . str ( " \" \" " ) ;
ASSERT_EQUALS ( 4 , CheckBufferOverrun : : countSprintfLength ( " str%s " , stringAsParameter ) ) ;
strTok . str ( " \" 12345 \" " ) ;
ASSERT_EQUALS ( 9 , CheckBufferOverrun : : countSprintfLength ( " str%s " , stringAsParameter ) ) ;
ASSERT_EQUALS ( 6 , CheckBufferOverrun : : countSprintfLength ( " %-4s " , stringAsParameter ) ) ;
ASSERT_EQUALS ( 6 , CheckBufferOverrun : : countSprintfLength ( " %-5s " , stringAsParameter ) ) ;
ASSERT_EQUALS ( 7 , CheckBufferOverrun : : countSprintfLength ( " %-6s " , stringAsParameter ) ) ;
ASSERT_EQUALS ( 5 , CheckBufferOverrun : : countSprintfLength ( " %.4s " , stringAsParameter ) ) ;
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 ) ) ;
Token numTok ;
numTok . str ( " 12345 " ) ;
std : : list < const Token * > intAsParameter ( 1 , & numTok ) ;
ASSERT_EQUALS ( 6 , CheckBufferOverrun : : countSprintfLength ( " %02ld " , intAsParameter ) ) ;
ASSERT_EQUALS ( 9 , CheckBufferOverrun : : countSprintfLength ( " %08ld " , intAsParameter ) ) ;
ASSERT_EQUALS ( 6 , CheckBufferOverrun : : countSprintfLength ( " %.2d " , intAsParameter ) ) ;
ASSERT_EQUALS ( 9 , CheckBufferOverrun : : countSprintfLength ( " %08.2d " , intAsParameter ) ) ;
TODO_ASSERT_EQUALS ( 5 , 2 , CheckBufferOverrun : : countSprintfLength ( " %x " , intAsParameter ) ) ;
ASSERT_EQUALS ( 5 , CheckBufferOverrun : : countSprintfLength ( " %4x " , intAsParameter ) ) ;
ASSERT_EQUALS ( 6 , CheckBufferOverrun : : countSprintfLength ( " %5x " , intAsParameter ) ) ;
ASSERT_EQUALS ( 5 , CheckBufferOverrun : : countSprintfLength ( " %.4x " , intAsParameter ) ) ;
ASSERT_EQUALS ( 6 , CheckBufferOverrun : : countSprintfLength ( " %.5x " , intAsParameter ) ) ;
ASSERT_EQUALS ( 6 , CheckBufferOverrun : : countSprintfLength ( " %1.5x " , intAsParameter ) ) ;
ASSERT_EQUALS ( 6 , CheckBufferOverrun : : countSprintfLength ( " %5.1x " , intAsParameter ) ) ;
Token floatTok ;
floatTok . str ( " 1.12345f " ) ;
std : : list < const Token * > floatAsParameter ( 1 , & floatTok ) ;
TODO_ASSERT_EQUALS ( 5 , 3 , CheckBufferOverrun : : countSprintfLength ( " %.2f " , floatAsParameter ) ) ;
ASSERT_EQUALS ( 9 , CheckBufferOverrun : : countSprintfLength ( " %8.2f " , floatAsParameter ) ) ;
TODO_ASSERT_EQUALS ( 5 , 3 , CheckBufferOverrun : : countSprintfLength ( " %2.2f " , floatAsParameter ) ) ;
Token floatTok2 ;
floatTok2 . str ( " 100.12345f " ) ;
std : : list < const Token * > floatAsParameter2 ( 1 , & floatTok2 ) ;
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 ) ) ;
std : : list < const Token * > multipleParams = { & strTok , nullptr , & numTok } ;
ASSERT_EQUALS ( 15 , CheckBufferOverrun : : countSprintfLength ( " str%s%d%d " , multipleParams ) ) ;
ASSERT_EQUALS ( 26 , CheckBufferOverrun : : countSprintfLength ( " str%-6s%08ld%08ld " , multipleParams ) ) ;
}
*/
2015-02-10 06:35:41 +01:00
void minsize_argvalue ( ) {
Settings settings ;
const char xmldata [ ] = " <?xml version= \" 1.0 \" ?> \n "
" <def> \n "
2015-02-12 17:36:22 +01:00
" <function name= \" mymemset \" > \n "
2015-02-10 06:35:41 +01:00
" <noreturn>false</noreturn> \n "
" <arg nr= \" 1 \" > \n "
" <minsize type= \" argvalue \" arg= \" 3 \" /> \n "
" </arg> \n "
" <arg nr= \" 2 \" /> \n "
" <arg nr= \" 3 \" /> \n "
" </function> \n "
" </def> " ;
tinyxml2 : : XMLDocument doc ;
doc . Parse ( xmldata , sizeof ( xmldata ) ) ;
settings . library . load ( doc ) ;
2015-02-14 15:46:00 +01:00
settings . addEnabled ( " warning " ) ;
Set correct type and size of string and char literals (#2275)
* Set correct type and size of string and char literals
Use that string and char literal tokens store the prefix. This makes
it possible to distinghuish between different type of string literals
(i.e., utf8 encoded strings, utf16, wide strings, etc) which have
different type.
When the tokens holding the string and character values have the correct
type, it is possible to improve Token::getStrSize() to give the correct
result for all string types. Previously, it would return the number of
characters in the string, i.e., it would give the wrong size unless
the type of the string was char*.
Since strings now can have different size (in number of bytes) and
length (in number of elements), add a new helper function that returns
the number of characters. Checkers have been updated to use the correct
functions.
Having the size makes it possible to find more problems with prefixed
strings, and to reduce false positives, for example in the buffer
overflow checker.
Also, improve the stringLiteralWrite error message to also print the
prefix of the string (if there is one).
* Add comment and update string length
2019-10-20 07:11:57 +02:00
settings . sizeof_wchar_t = 4 ;
2015-02-10 06:35:41 +01:00
check ( " void f() { \n "
" char c[10]; \n "
2015-02-12 17:36:22 +01:00
" mymemset(c, 0, 10); \n "
2015-02-10 06:35:41 +01:00
" } " , settings ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" char c[10]; \n "
2015-02-12 17:36:22 +01:00
" mymemset(c, 0, 11); \n "
2015-02-10 06:35:41 +01:00
" } " , settings ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Buffer is accessed out of bounds: c \n " , errout . str ( ) ) ;
2015-02-10 06:49:48 +01:00
2015-02-13 16:16:59 +01:00
check ( " struct S { \n "
" char a[5]; \n "
" }; \n "
" void f() { \n "
" S s; \n "
" mymemset(s.a, 0, 10); \n "
" } " , settings ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (error) Buffer is accessed out of bounds: s.a \n " , errout . str ( ) ) ;
2015-02-14 15:46:00 +01:00
check ( " void foo() { \n "
" char s[10]; \n "
" mymemset(s, 0, '*'); \n "
" } " , settings ) ;
2019-03-09 22:14:02 +01:00
// TODO ASSERT_EQUALS("[test.cpp:3]: (warning) The size argument is given as a char constant.\n", errout.str());
2015-02-14 15:46:00 +01:00
2015-02-10 06:49:48 +01:00
// ticket #836
2015-02-13 16:16:59 +01:00
check ( " void f(void) { \n "
2015-02-10 06:49:48 +01:00
" char a[10]; \n "
2015-02-12 17:36:22 +01:00
" mymemset(a+5, 0, 10); \n "
2015-02-10 06:49:48 +01:00
" } " , settings ) ;
2019-03-09 22:14:02 +01:00
TODO_ASSERT_EQUALS ( " [test.cpp:3]: (error) Buffer is accessed out of bounds: a \n " , " " , errout . str ( ) ) ;
2015-02-10 17:29:36 +01:00
2015-02-13 16:16:59 +01:00
// Ticket #909
check ( " void f(void) { \n "
" char str[] = \" abcd \" ; \n "
Set correct type and size of string and char literals (#2275)
* Set correct type and size of string and char literals
Use that string and char literal tokens store the prefix. This makes
it possible to distinghuish between different type of string literals
(i.e., utf8 encoded strings, utf16, wide strings, etc) which have
different type.
When the tokens holding the string and character values have the correct
type, it is possible to improve Token::getStrSize() to give the correct
result for all string types. Previously, it would return the number of
characters in the string, i.e., it would give the wrong size unless
the type of the string was char*.
Since strings now can have different size (in number of bytes) and
length (in number of elements), add a new helper function that returns
the number of characters. Checkers have been updated to use the correct
functions.
Having the size makes it possible to find more problems with prefixed
strings, and to reduce false positives, for example in the buffer
overflow checker.
Also, improve the stringLiteralWrite error message to also print the
prefix of the string (if there is one).
* Add comment and update string length
2019-10-20 07:11:57 +02:00
" mymemset(str, 0, 6); \n "
2015-02-13 16:16:59 +01:00
" } " , settings ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Buffer is accessed out of bounds: str \n " , errout . str ( ) ) ;
Set correct type and size of string and char literals (#2275)
* Set correct type and size of string and char literals
Use that string and char literal tokens store the prefix. This makes
it possible to distinghuish between different type of string literals
(i.e., utf8 encoded strings, utf16, wide strings, etc) which have
different type.
When the tokens holding the string and character values have the correct
type, it is possible to improve Token::getStrSize() to give the correct
result for all string types. Previously, it would return the number of
characters in the string, i.e., it would give the wrong size unless
the type of the string was char*.
Since strings now can have different size (in number of bytes) and
length (in number of elements), add a new helper function that returns
the number of characters. Checkers have been updated to use the correct
functions.
Having the size makes it possible to find more problems with prefixed
strings, and to reduce false positives, for example in the buffer
overflow checker.
Also, improve the stringLiteralWrite error message to also print the
prefix of the string (if there is one).
* Add comment and update string length
2019-10-20 07:11:57 +02:00
check ( " void f(void) { \n "
" char str[] = \" abcd \" ; \n "
" mymemset(str, 0, 5); \n "
" } " , settings ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(void) { \n "
" wchar_t str[] = L \" abcd \" ; \n "
" mymemset(str, 0, 21); \n "
" } " , settings ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Buffer is accessed out of bounds: str \n " , errout . str ( ) ) ;
check ( " void f(void) { \n "
" wchar_t str[] = L \" abcd \" ; \n "
" mymemset(str, 0, 20); \n "
" } " , settings ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-02-13 16:16:59 +01:00
// ticket #1659 - overflowing variable when using memcpy
2015-02-14 15:51:13 +01:00
check ( " void f(void) { \n "
" char c; \n "
" mymemset(&c, 0, 4); \n "
" } " , settings ) ;
2015-02-13 16:16:59 +01:00
TODO_ASSERT_EQUALS ( " [test.cpp:3]: (error) Buffer is accessed out of bounds: c \n " , " " , errout . str ( ) ) ;
// ticket #2121 - buffer access out of bounds when using uint32_t
check ( " void f(void) { \n "
" unknown_type_t buf[4]; \n "
" mymemset(buf, 0, 100); \n "
" } " , settings ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-02-14 16:37:48 +01:00
// #3124 - multidimension array
check ( " int main() { \n "
" char b[5][6]; \n "
" mymemset(b, 0, 5 * 6); \n "
" } " , settings ) ;
2019-10-07 09:17:12 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-02-14 16:37:48 +01:00
check ( " int main() { \n "
" char b[5][6]; \n "
" mymemset(b, 0, 6 * 6); \n "
" } " , settings ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Buffer is accessed out of bounds: b \n " , errout . str ( ) ) ;
2019-10-07 09:17:12 +02:00
check ( " int main() { \n "
" char b[5][6]; \n "
" mymemset(b, 0, 31); \n "
" } " , settings ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Buffer is accessed out of bounds: b \n " , errout . str ( ) ) ;
2015-02-10 17:29:36 +01:00
// #4968 - not standard function
check ( " void f() { \n "
" char str[3]; \n "
2015-02-12 17:36:22 +01:00
" foo.mymemset(str, 0, 100); \n "
" foo::mymemset(str, 0, 100); \n "
" std::mymemset(str, 0, 100); \n "
2015-02-10 17:29:36 +01:00
" } " , settings ) ;
TODO_ASSERT_EQUALS ( " [test.cpp:5]: (error) Buffer is accessed out of bounds: str \n " , " " , errout . str ( ) ) ;
// #5257 - check strings
check ( " void f() { \n "
2015-02-12 17:36:22 +01:00
" mymemset( \" abc \" , 0, 20); \n "
2015-02-10 17:29:36 +01:00
" } " , settings ) ;
2019-03-09 22:14:02 +01:00
// TODO ASSERT_EQUALS("[test.cpp:2]: (error) Buffer is accessed out of bounds.\n", errout.str());
2015-02-10 17:29:36 +01:00
check ( " void f() { \n "
2015-02-12 17:36:22 +01:00
" mymemset(temp, \" abc \" , 4); \n "
2015-02-10 17:29:36 +01:00
" } " , settings ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-07-27 16:39:41 +02:00
check ( " void f() { \n " // #6816 - fp when array has known string value
2019-03-09 22:14:02 +01:00
" char c[10] = \" c \" ; \n "
2015-07-27 16:39:41 +02:00
" mymemset(c, 0, 10); \n "
" } " , settings ) ;
2019-03-11 20:33:08 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-02-10 06:35:41 +01:00
}
2015-02-09 16:20:28 +01:00
void minsize_sizeof ( ) {
Settings settings ;
const char xmldata [ ] = " <?xml version= \" 1.0 \" ?> \n "
" <def> \n "
2015-02-12 17:36:22 +01:00
" <function name= \" mystrncpy \" > \n "
2015-02-09 16:20:28 +01:00
" <noreturn>false</noreturn> \n "
" <arg nr= \" 1 \" > \n "
2019-03-09 22:14:02 +01:00
" <minsize type= \" strlen \" arg= \" 2 \" /> \n "
2015-02-09 16:20:28 +01:00
" <minsize type= \" argvalue \" arg= \" 3 \" /> \n "
" </arg> \n "
" <arg nr= \" 2 \" /> \n "
" <arg nr= \" 3 \" /> \n "
" </function> \n "
" </def> " ;
tinyxml2 : : XMLDocument doc ;
doc . Parse ( xmldata , sizeof ( xmldata ) ) ;
settings . library . load ( doc ) ;
check ( " void f() { \n "
" char c[7]; \n "
2015-02-12 17:36:22 +01:00
" mystrncpy(c, \" hello \" , 7); \n "
2015-02-09 16:20:28 +01:00
" } " , settings ) ;
2010-04-21 20:02:58 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-09-25 22:32:18 +02:00
2015-02-09 16:20:28 +01:00
check ( " void f() { \n "
" char c[6]; \n "
2015-02-12 17:36:22 +01:00
" mystrncpy(c, \" hello \" ,6); \n "
2015-02-09 16:20:28 +01:00
" } " , settings ) ;
2009-09-25 22:32:18 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-02-09 16:20:28 +01:00
check ( " void f() { \n "
" char c[5]; \n "
2015-02-12 17:36:22 +01:00
" mystrncpy(c, \" hello \" ,6); \n "
2015-02-09 16:20:28 +01:00
" } " , settings ) ;
2013-04-13 08:19:14 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Buffer is accessed out of bounds: c \n " , errout . str ( ) ) ;
2009-09-25 22:32:18 +02:00
2015-02-09 16:20:28 +01:00
check ( " void f() { \n "
" char c[6]; \n "
2015-02-12 17:36:22 +01:00
" mystrncpy(c, \" hello! \" ,7); \n "
2015-02-09 16:20:28 +01:00
" } " , settings ) ;
2013-04-13 08:19:14 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Buffer is accessed out of bounds: c \n " , errout . str ( ) ) ;
2010-02-21 15:23:50 +01:00
2019-11-10 16:42:48 +01:00
check ( " void f(unsigned int addr) { \n "
" memset((void *)addr, 0, 1000); \n "
" } " , settings0 ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-02-09 16:20:28 +01:00
check ( " struct AB { char a[10]; }; \n "
" void foo(AB *ab) { \n "
2015-02-12 17:36:22 +01:00
" mystrncpy(x, ab->a, 100); \n "
2015-02-09 16:20:28 +01:00
" } " , settings ) ;
2010-04-21 20:02:58 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-02-10 06:35:41 +01:00
2015-02-12 17:36:22 +01:00
check ( " void a(char *p) { mystrncpy(p, \" hello world! \" ,10); } \n " // #3168
2015-02-10 06:35:41 +01:00
" void b() { \n "
" char buf[5]; \n "
" a(buf); "
" } " , settings ) ;
2019-03-09 22:14:02 +01:00
// TODO CTU ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:1]: (error) Buffer is accessed out of bounds: buf\n", errout.str());
2009-09-25 22:32:18 +02:00
}
2015-02-12 17:36:22 +01:00
2015-02-12 17:29:36 +01:00
void minsize_strlen ( ) {
Settings settings ;
const char xmldata [ ] = " <?xml version= \" 1.0 \" ?> \n "
" <def> \n "
" <function name= \" mysprintf \" > \n "
" <noreturn>false</noreturn> \n "
" <formatstr/> \n "
" <arg nr= \" 1 \" > \n "
" <minsize type= \" strlen \" arg= \" 2 \" /> \n "
" </arg> \n "
" <arg nr= \" 2 \" > \n "
" <formatstr/> \n "
" </arg> \n "
" </function> \n "
" </def> " ;
tinyxml2 : : XMLDocument doc ;
doc . Parse ( xmldata , sizeof ( xmldata ) ) ;
settings . library . load ( doc ) ;
// formatstr..
check ( " void f() { \n "
" char str[3]; \n "
" mysprintf(str, \" test \" ); \n "
" } " , settings ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Buffer is accessed out of bounds: str \n " , errout . str ( ) ) ;
check ( " void f() { \n "
" char str[5]; \n "
" mysprintf(str, \" %s \" , \" abcde \" ); \n "
" } " , settings ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Buffer is accessed out of bounds: str \n " , errout . str ( ) ) ;
check ( " int getnumber(); \n "
" void f() \n "
" { \n "
" char str[5]; \n "
" mysprintf(str, \" %d: %s \" , getnumber(), \" abcde \" ); \n "
" } " , settings ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (error) Buffer is accessed out of bounds: str \n " , errout . str ( ) ) ;
check ( " void f() { \n "
" char str[5]; \n "
" mysprintf(str, \" test%s \" , \" \" ); \n "
" } " , settings ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" char *str = new char[5]; \n "
" mysprintf(str, \" abcde \" ); \n "
" } " , settings ) ;
2019-03-09 22:14:02 +01:00
// TODO ASSERT_EQUALS("[test.cpp:3]: (error) Buffer is accessed out of bounds.\n", errout.str());
2015-02-12 17:29:36 +01:00
check ( " void f(int condition) { \n "
" char str[5]; \n "
" mysprintf(str, \" test%s \" , condition ? \" 12 \" : \" 34 \" ); \n "
" } " , settings ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int condition) { \n "
" char str[5]; \n "
" mysprintf(str, \" test%s \" , condition ? \" 12 \" : \" 345 \" ); \n "
" } " , settings ) ;
TODO_ASSERT_EQUALS ( " error " , " " , errout . str ( ) ) ;
check ( " struct Foo { char a[1]; }; \n "
" void f() { \n "
" struct Foo x; \n "
" mysprintf(x.a, \" aa \" ); \n "
" } " , settings ) ;
2019-03-09 22:14:02 +01:00
TODO_ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer is accessed out of bounds: x.a \n " , " " , errout . str ( ) ) ;
2015-02-12 17:29:36 +01:00
2015-02-14 16:29:05 +01:00
// ticket #900
check ( " void f() { \n "
" char *a = new char(30); \n "
" mysprintf(a, \" a \" ); \n "
" } " , settings ) ;
2019-03-09 22:14:02 +01:00
// TODO ASSERT_EQUALS("[test.cpp:3]: (error) Buffer is accessed out of bounds.\n", errout.str());
2015-02-14 16:29:05 +01:00
2015-03-25 12:56:45 +01:00
check ( " void f(char value) { \n "
" char *a = new char(value); \n "
" mysprintf(a, \" a \" ); \n "
" } " , settings ) ;
2019-03-09 22:14:02 +01:00
// TODO ASSERT_EQUALS("[test.cpp:3]: (error) Buffer is accessed out of bounds.\n", errout.str());
2015-03-25 12:56:45 +01:00
2015-02-12 17:29:36 +01:00
// This is out of bounds if 'sizeof(ABC)' is 1 (No padding)
check ( " struct Foo { char a[1]; }; \n "
" void f() { \n "
" struct Foo *x = malloc(sizeof(Foo)); \n "
" mysprintf(x.a, \" aa \" ); \n "
" } " , settings ) ;
2019-03-09 22:14:02 +01:00
// TODO ASSERT_EQUALS("", errout.str());
2015-02-12 17:29:36 +01:00
check ( " struct Foo { char a[1]; }; \n "
" void f() { \n "
" struct Foo *x = malloc(sizeof(Foo) + 10); \n "
" mysprintf(x.a, \" aa \" ); \n "
" } " , settings ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-06-07 14:01:20 +02:00
check ( " struct Foo { \n " // #6668 - unknown size
" char a[LEN]; \n "
" void f(); \n "
" }; "
" void Foo::f() { \n "
" mysprintf(a, \" abcd \" ); \n "
" } " , settings ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-02-12 17:29:36 +01:00
}
2009-11-15 16:44:30 +01:00
2015-02-10 06:44:19 +01:00
void minsize_mul ( ) {
Settings settings ;
const char xmldata [ ] = " <?xml version= \" 1.0 \" ?> \n "
" <def> \n "
2015-02-12 17:36:22 +01:00
" <function name= \" myfread \" > \n "
2015-02-10 06:44:19 +01:00
" <arg nr= \" 1 \" > \n "
" <minsize type= \" mul \" arg= \" 2 \" arg2= \" 3 \" /> \n "
" </arg> \n "
" <arg nr= \" 2 \" /> \n "
" <arg nr= \" 3 \" /> \n "
" <arg nr= \" 4 \" /> \n "
" </function> \n "
" </def> " ;
tinyxml2 : : XMLDocument doc ;
doc . Parse ( xmldata , sizeof ( xmldata ) ) ;
settings . library . load ( doc ) ;
check ( " void f() { \n "
" char c[5]; \n "
2015-02-12 17:36:22 +01:00
" myfread(c, 1, 5, stdin); \n "
2015-02-10 06:44:19 +01:00
" } " , settings ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" char c[5]; \n "
2015-02-12 17:36:22 +01:00
" myfread(c, 1, 6, stdin); \n "
2015-02-10 06:44:19 +01:00
" } " , settings ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Buffer is accessed out of bounds: c \n " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void unknownType ( ) {
2009-11-15 16:44:30 +01:00
check ( " void f() \n "
" { \n "
" UnknownType *a = malloc(4); \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2009-11-15 16:44:30 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-12-18 17:26:15 +01:00
2014-11-20 14:20:09 +01:00
void terminateStrncpy1 ( ) {
2013-04-13 08:19:14 +02:00
check ( " void foo ( char *bar ) { \n "
2009-12-18 17:26:15 +01:00
" char baz[100]; \n "
2013-04-13 08:19:14 +02:00
" strncpy(baz, bar, 100); \n "
" strncpy(baz, bar, 100); \n "
" baz[99] = 0; \n "
" strncpy(baz, bar, 100); \n "
2009-12-18 17:26:15 +01:00
" baz[99] = 0; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2019-03-12 21:15:26 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-04-05 20:47:50 +02:00
2016-11-24 07:04:58 +01:00
check ( " void foo ( char *bar ) { \n "
" char baz[100]; \n "
" strncpy(baz, bar, 100); \n "
" baz[99] = ' \\ 0'; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo ( char *bar ) { \n "
" char baz[100]; \n "
" strncpy(baz, bar, 100); \n "
" baz[x+1] = ' \\ 0'; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-04-05 20:47:50 +02:00
// Test with invalid code that there is no segfault
check ( " char baz[100]; \n "
2013-04-13 08:19:14 +02:00
" strncpy(baz, \" var \" , 100) \n " ) ;
2010-04-05 20:47:50 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// Test that there are no duplicate error messages
2013-04-13 08:19:14 +02:00
check ( " void foo ( char *bar ) { \n "
2010-04-05 20:47:50 +02:00
" char baz[100]; \n "
2013-04-13 08:19:14 +02:00
" strncpy(baz, bar, 100); \n "
2010-04-05 20:47:50 +02:00
" foo(baz); \n "
" foo(baz); \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2013-04-13 08:19:14 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (warning, inconclusive) The buffer 'baz' may not be null-terminated after the call to strncpy(). \n " , errout . str ( ) ) ;
2009-12-18 17:26:15 +01:00
}
2014-11-20 14:20:09 +01:00
void terminateStrncpy2 ( ) {
2013-04-13 08:19:14 +02:00
check ( " char *foo ( char *bar ) { \n "
2009-12-18 17:26:15 +01:00
" char baz[100]; \n "
2013-04-13 08:19:14 +02:00
" strncpy(baz, bar, 100); \n "
2009-12-18 17:26:15 +01:00
" bar[99] = 0; \n "
" return baz; \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2013-04-13 08:19:14 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (warning, inconclusive) The buffer 'baz' may not be null-terminated after the call to strncpy(). \n " , errout . str ( ) ) ;
2009-12-18 17:26:15 +01:00
}
2014-11-20 14:20:09 +01:00
void terminateStrncpy3 ( ) {
2010-11-07 09:37:45 +01:00
// 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 ) ;
2019-03-19 21:06:37 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (warning, inconclusive) The buffer 'str' may not be null-terminated after the call to strncpy(). \n " , errout . str ( ) ) ;
2010-11-07 09:37:45 +01:00
}
2019-03-06 18:50:50 +01:00
void terminateStrncpy4 ( ) {
check ( " void bar() { \n "
" char buf[4]; \n "
" strncpy(buf, \" ab \" , 4); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void bar() { \n "
" char buf[4]; \n "
" strncpy(buf, \" abcde \" , 4); \n "
" } \n " ) ;
2019-03-12 21:15:26 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (warning, inconclusive) The buffer 'buf' may not be null-terminated after the call to strncpy(). \n " , errout . str ( ) ) ;
2019-03-06 18:50:50 +01:00
}
2014-11-20 14:20:09 +01:00
void recursive_long_time ( ) {
2010-02-27 22:47:56 +01:00
// 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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2010-02-27 22:47:56 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-04-10 21:12:00 +02:00
2010-04-11 20:57:30 +02:00
// Ticket #1587 - crash
2014-11-20 14:20:09 +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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2010-04-11 20:57:30 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void crash2 ( ) {
2011-08-29 19:16:52 +02:00
check ( " void a(char *p) { \n "
" f( { if(finally_arg); } ); \n "
" } \n "
" \n "
" void b() { \n "
" char arr[64]; \n "
" a(arr); \n "
" } " ) ;
}
2014-11-20 14:20:09 +01:00
void crash3 ( ) {
2014-01-31 06:19:36 +01:00
check ( " struct b { unknown v[0]; }; \n "
" void d() { struct b *f; f = malloc(108); } " ) ;
}
2018-08-26 19:46:36 +02:00
void crash4 ( ) { // #8679
check ( " __thread void *thread_local_var; "
" int main() { "
" thread_local_var = malloc(1337); "
" return 0; "
" } " ) ;
check ( " thread_local void *thread_local_var; "
" int main() { "
" thread_local_var = malloc(1337); "
" return 0; "
" } " ) ;
}
2010-04-10 21:12:00 +02:00
2018-08-30 10:01:19 +02:00
void crash5 ( ) { // 8644 - token has varId() but variable() is null
check ( " int a() { \n "
" void b(char **dst) { \n "
" *dst = malloc(50); \n "
" } \n "
" } " ) ;
}
2019-03-29 19:37:23 +01:00
void crash6 ( ) {
2019-03-08 11:07:33 +01:00
check ( " void start(char* name) { \n "
" char snapname[64] = { 0 }; \n "
" strncpy(snapname, \" snapshot \" , arrayLength(snapname)); \n "
" } " ) ;
}
2019-03-29 19:37:23 +01:00
void crash7 ( ) { // 9073 - [ has no astParent
check ( " char x[10]; \n "
" void f() { x[10]; } " ) ;
}
2018-10-19 11:04:15 +02:00
void insecureCmdLineArgs ( ) {
check ( " int main(int argc, char *argv[]) \n "
" { \n "
" if(argc>1) \n "
" { \n "
" char buf[2]; \n "
" char *p = strdup(argv[1]); \n "
" strcpy(buf,p); \n "
" free(p); \n "
" } \n "
" return 0; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:7]: (error) Buffer overrun possible for long command line arguments. \n " , errout . str ( ) ) ;
check ( " int main(int argc, char *argv[]) \n "
" { \n "
" if(argc>1) \n "
" { \n "
" char buf[2] = {' \\ 0',' \\ 0'}; \n "
" char *p = strdup(argv[1]); \n "
" strcat(buf,p); \n "
" free(p); \n "
" } \n "
" return 0; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:7]: (error) Buffer overrun possible for long command line arguments. \n " , errout . str ( ) ) ;
2018-10-15 10:05:43 +02:00
check ( " int main(const int argc, char* argv[]) \n "
" { \n "
" char prog[10]; \n "
" strcpy(prog, argv[0]); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer overrun possible for long command line arguments. \n " , errout . str ( ) ) ;
check ( " int main(int argc, const char* argv[]) \n "
" { \n "
" char prog[10]; \n "
" strcpy(prog, argv[0]); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer overrun possible for long command line arguments. \n " , errout . str ( ) ) ;
check ( " int main(const int argc, const char* argv[]) \n "
2010-06-02 18:09:25 +02:00
" { \n "
" char prog[10]; \n "
" strcpy(prog, argv[0]); \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-09 11:11:05 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer overrun possible for long command line arguments. \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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-09 11:11:05 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer overrun possible for long command line arguments. \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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-09 11:11:05 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer overrun possible for long command line arguments. \n " , errout . str ( ) ) ;
2010-06-02 18:09:25 +02:00
2019-08-15 08:45:31 +02:00
check ( " int main(int argc, const char *const *const argv, char **envp) \n "
" { \n "
" char prog[10]; \n "
" strcpy(prog, argv[0]); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer overrun possible for long command line arguments. \n " , errout . str ( ) ) ;
check ( " int main(const int argc, const char *const *const argv, const char *const *const envp) \n "
" { \n "
" char prog[10]; \n "
" strcpy(prog, argv[0]); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer overrun possible for long command line arguments. \n " , 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 "
" strcat(prog, argv[0]); \n "
2018-10-15 10:05:43 +02:00
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer overrun possible for long command line arguments. \n " , errout . str ( ) ) ;
check ( " int main(const int argc, const char **argv, char **envp) \n "
" { \n "
" char prog[10] = {' \\ 0'}; \n "
" strcat(prog, argv[0]); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer overrun possible for long command line arguments. \n " , errout . str ( ) ) ;
check ( " int main(int argc, const char **argv, char **envp) \n "
" { \n "
" char prog[10] = {' \\ 0'}; \n "
" strcat(prog, argv[0]); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer overrun possible for long command line arguments. \n " , errout . str ( ) ) ;
check ( " int main(const int argc, char **argv, char **envp) \n "
" { \n "
" char prog[10] = {' \\ 0'}; \n "
" strcat(prog, argv[0]); \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-09 11:11:05 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer overrun possible for long command line arguments. \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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-09 11:11:05 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer overrun possible for long command line arguments. \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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-09 11:11:05 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer overrun possible for long command line arguments. \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 "
2015-02-12 17:29:36 +01:00
" strcpy(prog, *options); \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2012-07-09 11:11:05 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer overrun possible for long command line arguments. \n " , errout . str ( ) ) ;
2010-06-02 18:09:25 +02:00
2017-03-27 11:30:07 +02:00
check ( " int main(int argc, char **options) \n "
" { \n "
" char prog[10]; \n "
" strcpy(prog+3, *options); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer overrun possible for long command line arguments. \n " , 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 "
" if (strlen(argv[0]) < 10) \n "
" strcpy(prog, argv[0]); \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2010-06-02 18:09:25 +02:00
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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2010-06-02 07:41:07 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-09-29 15:38:33 +02:00
// #5835
2015-02-14 16:44:08 +01:00
check ( " int main(int argc, char* argv[]) { \n "
" char prog[10]; \n "
" strcpy(prog, argv[0]); \n "
" strcpy(prog, argv[0]); \n "
" } " ) ;
2014-09-29 15:38:33 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Buffer overrun possible for long command line arguments. \n "
" [test.cpp:4]: (error) Buffer overrun possible for long command line arguments. \n " , errout . str ( ) ) ;
2017-04-21 23:36:10 +02:00
// #7964
check ( " int main(int argc, char *argv[]) { \n "
" char *strcpy(); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " int main(int argc, char *argv[]) { \n "
" char *strcat(); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-06-02 07:41:07 +02:00
}
2010-08-24 22:03:18 +02:00
2015-02-14 16:29:05 +01:00
void checkBufferAllocatedWithStrlen ( ) {
check ( " void f(char *a) { \n "
" char *b = new char[strlen(a)]; \n "
" strcpy(b, a); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Buffer is accessed out of bounds. \n " , errout . str ( ) ) ;
check ( " void f(char *a) { \n "
" char *b = new char[strlen(a) + 1]; \n "
" strcpy(b, a); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(char *a) { \n "
" char *b = new char[strlen(a)]; \n "
" a[0] = ' \\ 0'; \n "
" strcpy(b, a); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(char *a) { \n "
" char *b = malloc(strlen(a)); \n "
" b = realloc(b, 10000); \n "
" strcpy(b, a); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(char *a) { \n "
" char *b = malloc(strlen(a)); \n "
" strcpy(b, a); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Buffer is accessed out of bounds. \n " , errout . str ( ) ) ;
check ( " void f(char *a) { \n "
" char *b = malloc(strlen(a)); \n "
" { \n "
" strcpy(b, a); \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Buffer is accessed out of bounds. \n " , errout . str ( ) ) ;
check ( " void f(char *a) { \n "
" char *b = malloc(strlen(a) + 1); \n "
" strcpy(b, a); \n "
2015-02-14 16:37:48 +01:00
" } " ) ;
2015-02-14 16:29:05 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(char *a, char *c) { \n "
" char *b = realloc(c, strlen(a)); \n "
" strcpy(b, a); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Buffer is accessed out of bounds. \n " , errout . str ( ) ) ;
check ( " void f(char *a, char *c) { \n "
" char *b = realloc(c, strlen(a) + 1); \n "
" strcpy(b, a); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(char *a) { \n "
" char *b = malloc(strlen(a)); \n "
" strcpy(b, a); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Buffer is accessed out of bounds. \n " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void scope ( ) {
2010-08-24 22:03:18 +02:00
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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2010-08-24 22:03:18 +02:00
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 "
2013-03-14 09:45:47 +01:00
" } " ) ;
2014-06-26 17:36:20 +02:00
ASSERT_EQUALS ( " [test.cpp:9]: (error) Array 'x.buf[10]' accessed at index 10, which is out of bounds. \n " , errout . str ( ) ) ;
2010-08-24 22:03:18 +02:00
}
2010-12-13 18:17:33 +01:00
2014-11-20 14:20:09 +01:00
void getErrorMessages ( ) {
2010-12-16 20:15:22 +01:00
// Ticket #2292: segmentation fault when using --errorlist
CheckBufferOverrun c ;
2019-06-30 21:39:22 +02:00
c . getErrorMessages ( this , nullptr ) ;
2010-12-16 20:15:22 +01:00
}
2011-03-13 17:52:45 +01:00
2014-11-20 14:20:09 +01:00
void arrayIndexThenCheck ( ) {
2011-08-04 11:15:14 +02:00
check ( " void f(const char s[]) { \n "
" if (s[i] == 'x' && i < y) { \n "
" } "
" } " ) ;
2014-05-03 09:30:30 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ; // No message because i is unknown and thus gets no varid. Avoid an internalError here.
check ( " void f(const char s[], int i) { \n "
" if (s[i] == 'x' && i < y) { \n "
" } "
" } " ) ;
2012-07-08 15:51:24 +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 "
2014-05-03 09:30:30 +02:00
" for (int i = 0; s[i] == 'x' && i < y; ++i) { \n "
2011-08-04 11:15:14 +02:00
" } "
" } " ) ;
2012-07-08 15:51:24 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Array index 'i' is used before limits check. \n " , errout . str ( ) ) ;
2013-08-23 17:04:01 +02:00
check ( " void f(const int a[], unsigned i) { \n "
" if((a[i] < 2) && (i <= 42)) { \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (style) Array index 'i' is used before limits check. \n " , errout . str ( ) ) ;
2014-05-03 09:30:30 +02:00
check ( " void f(const int a[], unsigned i) { \n "
" if((a[i] < 2) && (42 >= i)) { \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (style) Array index 'i' is used before limits check. \n " , errout . str ( ) ) ;
2014-05-24 17:48:08 +02:00
check ( " void f(char* e, int y) { \n "
" if (e[y] == '/' && elen > y + 1 && e[y + 1] == '?') { \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2013-08-23 17:04:01 +02:00
check ( " void f(const int a[], unsigned i) { \n "
" if(a[i] < func(i) && i <= 42) { \n "
" } \n "
" } " ) ;
2017-03-27 11:07:34 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Array index 'i' is used before limits check. \n " , errout . str ( ) ) ;
check ( " void f(const int a[], unsigned i) { \n "
" if (i <= 42 && a[i] < func(i)) { \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(const int a[], unsigned i) { \n "
" if (foo(a[i] + 3) < func(i) && i <= 42) { \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (style) Array index 'i' is used before limits check. \n " , errout . str ( ) ) ;
2016-01-24 14:06:02 +01:00
check ( " void f(int i) { \n " // sizeof
" sizeof(a)/sizeof(a[i]) && i < 10; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-12-20 09:46:01 +01:00
check ( " void f(int i) { \n " // ?:
" if ((i < 10 ? buf[i] : 1) && (i < 5 ? buf[i] : 5)){} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-08-04 11:15:14 +02:00
}
2011-09-05 21:59:41 +02:00
2014-11-20 14:20:09 +01:00
void bufferNotZeroTerminated ( ) {
2013-04-13 08:19:14 +02:00
check ( " void f() { \n "
2011-09-05 21:59:41 +02:00
" char c[6]; \n "
2013-04-13 08:19:14 +02:00
" strncpy(c, \" hello! \" ,6); \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2013-04-13 08:19:14 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (warning, inconclusive) The buffer 'c' is not null-terminated after the call to strncpy(). \n " , errout . str ( ) ) ;
2011-09-05 21:59:41 +02:00
2013-04-13 08:19:14 +02:00
check ( " void f() { \n "
2011-09-05 21:59:41 +02:00
" char c[6]; \n "
2013-04-13 08:19:14 +02:00
" memcpy(c, \" hello! \" ,6); \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2013-04-13 08:19:14 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (warning, inconclusive) The buffer 'c' is not null-terminated after the call to memcpy(). \n " , errout . str ( ) ) ;
2011-09-05 21:59:41 +02:00
2013-04-13 08:19:14 +02:00
check ( " void f() { \n "
2011-09-05 21:59:41 +02:00
" char c[6]; \n "
2013-04-13 08:19:14 +02:00
" memmove(c, \" hello! \" ,6); \n "
2013-03-14 09:45:47 +01:00
" } " ) ;
2013-04-13 08:19:14 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (warning, inconclusive) The buffer 'c' is not null-terminated after the call to memmove(). \n " , errout . str ( ) ) ;
2011-09-05 21:59:41 +02:00
}
2008-12-18 22:28:57 +01:00
2014-11-20 14:20:09 +01:00
void negativeMemoryAllocationSizeError ( ) { // #389
2014-02-01 22:38:29 +01:00
check ( " void f() \n "
" { \n "
" int *a; \n "
" a = new int[-1]; \n "
" delete [] a; \n "
" } \n " ) ;
2014-04-08 20:23:00 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Memory allocation size is negative. \n " , errout . str ( ) ) ;
2014-02-01 22:38:29 +01:00
check ( " void f() \n "
" { \n "
" int *a; \n "
" a = malloc( -10 ); \n "
" free(a); \n "
" } \n " ) ;
2014-04-08 20:23:00 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Memory allocation size is negative. \n " , errout . str ( ) ) ;
2014-02-01 22:38:29 +01:00
check ( " void f() \n "
" { \n "
" int *a; \n "
" a = malloc( -10); \n "
" free(a); \n "
" } \n " ) ;
2014-04-08 20:23:00 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Memory allocation size is negative. \n " , errout . str ( ) ) ;
2014-02-01 22:38:29 +01:00
check ( " void f() \n "
" { \n "
" int *a; \n "
" a = alloca( -10 ); \n "
" free(a); \n "
" } \n " ) ;
2014-04-08 20:23:00 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Memory allocation size is negative. \n " , errout . str ( ) ) ;
2014-02-01 22:38:29 +01:00
}
2014-12-04 20:49:58 +01:00
2015-05-03 15:00:47 +02:00
void negativeArraySize ( ) {
check ( " void f(int sz) { \n " // #1760 - VLA
" int a[sz]; \n "
" } \n "
" void x() { f(-100); } " ) ;
2018-12-18 14:36:49 +01:00
TODO_ASSERT_EQUALS ( " [test.cpp:2]: (error) Declaration of array 'a' with negative size is undefined behaviour \n " , " " , errout . str ( ) ) ;
2015-07-04 09:42:42 +02:00
// don't warn for constant sizes -> this is a compiler error so this is used for static assertions for instance
check ( " int x, y; \n "
" int a[-1]; \n "
" int b[x?1:-1]; \n "
" int c[x?y:-1]; \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-05-03 15:00:47 +02:00
}
2019-03-17 13:40:56 +01:00
void pointerAddition1 ( ) {
check ( " void f() { \n "
" char arr[10]; \n "
" p = arr + 20; \n "
2019-07-29 08:06:57 +02:00
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (portability) Undefined behaviour, pointer arithmetic 'arr+20' is out of bounds. \n " , errout . str ( ) ) ;
2019-03-17 13:40:56 +01:00
}
2019-03-23 08:36:10 +01:00
void ctu ( const char code [ ] ) {
// Clear the error buffer..
errout . str ( " " ) ;
// Tokenize..
Tokenizer tokenizer ( & settings0 , this ) ;
std : : istringstream istr ( code ) ;
tokenizer . tokenize ( istr , " test.cpp " ) ;
CTU : : FileInfo * ctu = CTU : : getFileInfo ( & tokenizer ) ;
// Check code..
std : : list < Check : : FileInfo * > fileInfo ;
CheckBufferOverrun check ( & tokenizer , & settings0 , this ) ;
fileInfo . push_back ( check . getFileInfo ( & tokenizer , & settings0 ) ) ;
check . analyseWholeProgram ( ctu , fileInfo , settings0 , * this ) ;
while ( ! fileInfo . empty ( ) ) {
delete fileInfo . back ( ) ;
fileInfo . pop_back ( ) ;
}
delete ctu ;
}
2019-03-23 15:57:17 +01:00
void ctu_malloc ( ) {
2019-03-23 11:20:35 +01:00
ctu ( " void dostuff(char *p) { \n "
2019-03-23 08:36:10 +01:00
" p[-3] = 0; \n "
" } \n "
" \n "
" int main() { \n "
" char *s = malloc(4); \n "
" dostuff(s); \n "
" } " ) ;
2019-04-03 06:43:56 +02:00
ASSERT_EQUALS ( " [test.cpp:6] -> [test.cpp:7] -> [test.cpp:2]: (error) Array index out of bounds; buffer 'p' is accessed at offset -3. \n " , errout . str ( ) ) ;
2019-03-23 08:36:10 +01:00
2019-03-23 11:20:35 +01:00
ctu ( " void dostuff(char *p) { \n "
2019-03-23 08:36:10 +01:00
" p[4] = 0; \n "
" } \n "
" \n "
" int main() { \n "
" char *s = malloc(4); \n "
" dostuff(s); \n "
" } " ) ;
2019-04-03 06:43:56 +02:00
ASSERT_EQUALS ( " [test.cpp:6] -> [test.cpp:7] -> [test.cpp:2]: (error) Array index out of bounds; 'p' buffer size is 4 and it is accessed at offset 4. \n " , errout . str ( ) ) ;
2019-03-23 08:36:10 +01:00
}
2019-03-23 11:20:35 +01:00
2019-03-23 15:57:17 +01:00
void ctu_array ( ) {
2019-03-23 11:20:35 +01:00
ctu ( " void dostuff(char *p) { \n "
" p[10] = 0; \n "
" } \n "
" int main() { \n "
" char str[4]; \n "
" dostuff(str); \n "
" } " ) ;
2019-04-03 06:43:56 +02:00
ASSERT_EQUALS ( " [test.cpp:6] -> [test.cpp:2]: (error) Array index out of bounds; 'p' buffer size is 4 and it is accessed at offset 10. \n " , errout . str ( ) ) ;
2019-03-30 15:10:00 +01:00
ctu ( " static void memclr( char *data ) \n "
" { \n "
" data[10] = 0; \n "
" } \n "
" \n "
" static void f() \n "
" { \n "
" char str[5]; \n "
" memclr( str ); \n "
" } " ) ;
2019-04-03 06:43:56 +02:00
ASSERT_EQUALS ( " [test.cpp:9] -> [test.cpp:3]: (error) Array index out of bounds; 'data' buffer size is 5 and it is accessed at offset 10. \n " , errout . str ( ) ) ;
2019-03-30 15:10:00 +01:00
ctu ( " 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 ); \n "
" } " ) ;
2019-04-03 06:43:56 +02:00
ASSERT_EQUALS ( " [test.cpp:9] -> [test.cpp:3]: (error) Array index out of bounds; 'data' buffer size is 5 and it is accessed at offset 10. \n " , errout . str ( ) ) ;
2019-03-30 15:10:00 +01:00
ctu ( " 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 ); \n "
" } " ) ;
TODO_ASSERT_EQUALS ( " [test.cpp:9] -> [test.cpp:3]: (possible error) Array index out of bounds. \n " ,
" " , errout . str ( ) ) ;
// This is not an error
ctu ( " 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 ); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// #2097
ctu ( " 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 "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-05-01 13:00:14 +02:00
// #9112
ctu ( " static void get_mac_address(const u8 *strbuf) \n "
" { \n "
" (strbuf[2]); \n "
" } \n "
" \n "
" static void program_mac_address(u32 mem_base) \n "
" { \n "
" u8 macstrbuf[17] = { 0 }; \n "
" get_mac_address(macstrbuf); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-03-23 11:20:35 +01:00
}
2019-03-23 15:57:17 +01:00
void ctu_variable ( ) {
ctu ( " void dostuff(int *p) { \n "
" p[10] = 0; \n "
" } \n "
" int main() { \n "
" int x = 4; \n "
" dostuff(&x); \n "
" } " ) ;
2019-04-03 06:43:56 +02:00
ASSERT_EQUALS ( " [test.cpp:6] -> [test.cpp:2]: (error) Array index out of bounds; 'p' buffer size is 4 and it is accessed at offset 40. \n " , errout . str ( ) ) ;
}
void ctu_arithmetic ( ) {
ctu ( " void dostuff(int *p) { x = p + 10; } \n "
" int main() { \n "
" int x[3]; \n "
" dostuff(x); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:1]: (error) Pointer arithmetic overflow; 'p' buffer size is 12 \n " , errout . str ( ) ) ;
2019-03-23 15:57:17 +01:00
}
2019-05-31 11:16:04 +02:00
void objectIndex ( ) {
check ( " int f() { \n "
" int i; \n "
" return (&i)[1]; \n "
" } \n " ) ;
ASSERT_EQUALS (
" [test.cpp:3] -> [test.cpp:3]: (error) The address of local variable 'i' is accessed at non-zero index. \n " ,
errout . str ( ) ) ;
check ( " int f(int j) { \n "
" int i; \n "
" return (&i)[j]; \n "
" } \n " ) ;
ASSERT_EQUALS (
" [test.cpp:3] -> [test.cpp:3]: (warning) The address of local variable 'i' might be accessed at non-zero index. \n " ,
errout . str ( ) ) ;
check ( " int f() { \n "
" int i; \n "
" return (&i)[0]; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " int f(int * i) { \n "
" return i[1]; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " int f(std::vector<int> i) { \n "
" return i[1]; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " int f(std::vector<int> i) { \n "
" return i.data()[1]; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " int* f(std::vector<int>& i) { \n "
" return &(i[1]); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct A { int i; int j; }; \n "
" int f() { \n "
" A x; \n "
" return (&x.i)[0]; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct A { int i; int j; }; \n "
" int f() { \n "
" A x; \n "
" int * i = &x.i; \n "
" return i[0]; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-01-04 11:39:52 +01:00
check ( " void f() { \n "
" int x = 0; \n "
" std::map<int, int*> m; \n "
" m[0] = &x; \n "
" m[1] = &x; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " int f() { \n "
" int x = 0; \n "
" std::map<int, int*> m; \n "
" m[0] = &x; \n "
" return m[0][1]; \n "
" } \n " ) ;
ASSERT_EQUALS (
" [test.cpp:4] -> [test.cpp:5]: (error) The address of local variable 'x' is accessed at non-zero index. \n " ,
errout . str ( ) ) ;
check ( " int f(int * y) { \n "
" int x = 0; \n "
" std::map<int, int*> m; \n "
" m[0] = &x; \n "
" m[1] = y; \n "
" return m[1][1]; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-05-31 11:16:04 +02:00
}
2011-10-14 19:45:51 +02:00
} ;
REGISTER_TEST ( TestBufferOverrun )