2019-05-23 23:49:04 +08:00
/ / RUN : % clang_analyze_cc1 - verify % s - Wno - null - dereference \
/ / RUN : - analyzer - checker = core \
/ / RUN : - analyzer - checker = unix . cstring \
/ / RUN : - analyzer - checker = unix . Malloc \
/ / RUN : - analyzer - checker = alpha . unix . cstring \
/ / RUN : - analyzer - checker = debug . ExprInspection \
// RUN: -analyzer-config eagerly-assume=false
//
/ / RUN : % clang_analyze_cc1 - verify % s - Wno - null - dereference - DUSE_BUILTINS \
/ / RUN : - analyzer - checker = core \
/ / RUN : - analyzer - checker = unix . cstring \
/ / RUN : - analyzer - checker = unix . Malloc \
/ / RUN : - analyzer - checker = alpha . unix . cstring \
/ / RUN : - analyzer - checker = debug . ExprInspection \
// RUN: -analyzer-config eagerly-assume=false
//
/ / RUN : % clang_analyze_cc1 - verify % s - Wno - null - dereference - DVARIANT \
/ / RUN : - analyzer - checker = core \
/ / RUN : - analyzer - checker = unix . cstring \
/ / RUN : - analyzer - checker = unix . Malloc \
/ / RUN : - analyzer - checker = alpha . unix . cstring \
/ / RUN : - analyzer - checker = debug . ExprInspection \
// RUN: -analyzer-config eagerly-assume=false
//
/ / RUN : % clang_analyze_cc1 - verify % s - Wno - null - dereference \
/ / RUN : - DUSE_BUILTINS - DVARIANT \
/ / RUN : - analyzer - checker = core \
/ / RUN : - analyzer - checker = alpha . security . taint \
/ / RUN : - analyzer - checker = unix . cstring \
/ / RUN : - analyzer - checker = unix . Malloc \
/ / RUN : - analyzer - checker = alpha . unix . cstring \
/ / RUN : - analyzer - checker = debug . ExprInspection \
// RUN: -analyzer-config eagerly-assume=false
//
/ / RUN : % clang_analyze_cc1 - verify % s - Wno - null - dereference \
/ / RUN : - DSUPPRESS_OUT_OF_BOUND \
/ / RUN : - analyzer - checker = core \
/ / RUN : - analyzer - checker = unix . cstring \
/ / RUN : - analyzer - checker = unix . Malloc \
/ / RUN : - analyzer - checker = alpha . unix . cstring . BufferOverlap \
/ / RUN : - analyzer - checker = alpha . unix . cstring . NotNullTerminated \
/ / RUN : - analyzer - checker = debug . ExprInspection \
// RUN: -analyzer-config eagerly-assume=false
2010-07-27 09:37:31 +08:00
//===----------------------------------------------------------------------===
// Declarations
//===----------------------------------------------------------------------===
// Some functions are so similar to each other that they follow the same code
// path, such as memcpy and __memcpy_chk, or memcmp and bcmp. If VARIANT is
// defined, make sure to use the variants instead to make sure they are still
// checked by the analyzer.
// Some functions are implemented as builtins. These should be #defined as
// BUILTIN(f), which will prepend "__builtin_" if USE_BUILTINS is defined.
2011-04-15 13:22:18 +08:00
// Functions that have variants and are also available as builtins should be
2010-07-27 09:37:31 +08:00
// declared carefully! See memcpy() for an example.
# ifdef USE_BUILTINS
# define BUILTIN(f) __builtin_ ## f
# else /* USE_BUILTINS */
# define BUILTIN(f) f
# endif /* USE_BUILTINS */
2010-08-16 15:51:42 +08:00
# define NULL 0
2010-07-27 09:37:31 +08:00
typedef typeof ( sizeof ( int ) ) size_t ;
2012-05-17 00:01:10 +08:00
void clang_analyzer_eval ( int ) ;
2011-12-12 02:43:40 +08:00
int scanf ( const char * restrict format , . . . ) ;
2018-07-13 21:44:44 +08:00
void * malloc ( size_t ) ;
void free ( void * ) ;
2010-07-27 09:37:31 +08:00
//===----------------------------------------------------------------------===
// strlen()
//===----------------------------------------------------------------------===
# define strlen BUILTIN(strlen)
size_t strlen ( const char * s ) ;
void strlen_constant0 ( ) {
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strlen ( " 123 " ) = = 3 ) ; // expected-warning{{TRUE}}
2010-07-27 09:37:31 +08:00
}
void strlen_constant1 ( ) {
const char * a = " 123 " ;
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strlen ( a ) = = 3 ) ; // expected-warning{{TRUE}}
2010-07-27 09:37:31 +08:00
}
void strlen_constant2 ( char x ) {
char a [ ] = " 123 " ;
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strlen ( a ) = = 3 ) ; // expected-warning{{TRUE}}
2010-07-27 09:37:31 +08:00
a [ 0 ] = x ;
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strlen ( a ) = = 3 ) ; // expected-warning{{UNKNOWN}}
2010-07-27 09:37:31 +08:00
}
size_t strlen_null ( ) {
2019-12-11 08:48:17 +08:00
return strlen ( 0 ) ; // expected-warning{{Null pointer passed as 1st argument to string length function}}
2010-07-27 09:37:31 +08:00
}
size_t strlen_fn ( ) {
2011-06-20 10:06:40 +08:00
return strlen ( ( char * ) & strlen_fn ) ; // expected-warning{{Argument to string length function is the address of the function 'strlen_fn', which is not a null-terminated string}}
2010-07-27 09:37:31 +08:00
}
size_t strlen_nonloc ( ) {
label :
2011-06-20 10:06:40 +08:00
return strlen ( ( char * ) & & label ) ; // expected-warning{{Argument to string length function is the address of the label 'label', which is not a null-terminated string}}
2010-07-27 09:37:31 +08:00
}
2010-08-15 05:02:52 +08:00
void strlen_subregion ( ) {
2011-03-08 06:57:45 +08:00
struct two_strings { char a [ 2 ] , b [ 2 ] ; } ;
2010-08-15 05:02:52 +08:00
extern void use_two_strings ( struct two_strings * ) ;
struct two_strings z ;
use_two_strings ( & z ) ;
size_t a = strlen ( z . a ) ;
z . b [ 0 ] = 5 ;
size_t b = strlen ( z . a ) ;
2012-05-17 00:01:10 +08:00
if ( a = = 0 )
clang_analyzer_eval ( b = = 0 ) ; // expected-warning{{TRUE}}
2010-08-15 05:02:52 +08:00
use_two_strings ( & z ) ;
size_t c = strlen ( z . a ) ;
2012-05-17 00:01:10 +08:00
if ( a = = 0 )
clang_analyzer_eval ( c = = 0 ) ; // expected-warning{{UNKNOWN}}
2010-08-15 05:02:52 +08:00
}
extern void use_string ( char * ) ;
void strlen_argument ( char * x ) {
size_t a = strlen ( x ) ;
size_t b = strlen ( x ) ;
2012-05-17 00:01:10 +08:00
if ( a = = 0 )
clang_analyzer_eval ( b = = 0 ) ; // expected-warning{{TRUE}}
2010-08-15 05:02:52 +08:00
use_string ( x ) ;
size_t c = strlen ( x ) ;
2012-05-17 00:01:10 +08:00
if ( a = = 0 )
clang_analyzer_eval ( c = = 0 ) ; // expected-warning{{UNKNOWN}}
2010-08-15 05:02:52 +08:00
}
extern char global_str [ ] ;
void strlen_global ( ) {
size_t a = strlen ( global_str ) ;
size_t b = strlen ( global_str ) ;
2012-05-17 00:01:10 +08:00
if ( a = = 0 ) {
clang_analyzer_eval ( b = = 0 ) ; // expected-warning{{TRUE}}
// Make sure clang_analyzer_eval does not invalidate globals.
2018-07-13 21:44:44 +08:00
clang_analyzer_eval ( strlen ( global_str ) = = 0 ) ; // expected-warning{{TRUE}}
2012-05-17 00:01:10 +08:00
}
2010-08-15 05:02:52 +08:00
// Call a function with unknown effects, which should invalidate globals.
use_string ( 0 ) ;
size_t c = strlen ( global_str ) ;
2012-05-17 00:01:10 +08:00
if ( a = = 0 )
clang_analyzer_eval ( c = = 0 ) ; // expected-warning{{UNKNOWN}}
2010-08-15 05:02:52 +08:00
}
void strlen_indirect ( char * x ) {
size_t a = strlen ( x ) ;
char * p = x ;
char * * p2 = & p ;
size_t b = strlen ( x ) ;
2012-05-17 00:01:10 +08:00
if ( a = = 0 )
clang_analyzer_eval ( b = = 0 ) ; // expected-warning{{TRUE}}
2010-08-15 05:02:52 +08:00
extern void use_string_ptr ( char * const * ) ;
use_string_ptr ( p2 ) ;
size_t c = strlen ( x ) ;
2012-05-17 00:01:10 +08:00
if ( a = = 0 )
clang_analyzer_eval ( c = = 0 ) ; // expected-warning{{UNKNOWN}}
2010-08-15 05:02:52 +08:00
}
2011-12-21 06:35:30 +08:00
void strlen_indirect2 ( char * x ) {
size_t a = strlen ( x ) ;
char * p = x ;
char * * p2 = & p ;
extern void use_string_ptr2 ( char * * ) ;
use_string_ptr2 ( p2 ) ;
size_t c = strlen ( x ) ;
2012-05-17 00:01:10 +08:00
if ( a = = 0 )
clang_analyzer_eval ( c = = 0 ) ; // expected-warning{{UNKNOWN}}
2011-12-21 06:35:30 +08:00
}
2010-08-15 05:02:52 +08:00
void strlen_liveness ( const char * x ) {
if ( strlen ( x ) < 5 )
return ;
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strlen ( x ) < 5 ) ; // expected-warning{{FALSE}}
2010-08-15 05:02:52 +08:00
}
2010-08-16 15:51:42 +08:00
2016-08-17 23:37:52 +08:00
size_t strlenWrapper ( const char * str ) {
return strlen ( str ) ;
}
extern void invalidate ( char * s ) ;
void testStrlenCallee ( ) {
char str [ 42 ] ;
invalidate ( str ) ;
size_t lenBefore = strlenWrapper ( str ) ;
invalidate ( str ) ;
size_t lenAfter = strlenWrapper ( str ) ;
clang_analyzer_eval ( lenBefore = = lenAfter ) ; // expected-warning{{UNKNOWN}}
}
2011-02-22 12:55:05 +08:00
//===----------------------------------------------------------------------===
// strnlen()
//===----------------------------------------------------------------------===
size_t strnlen ( const char * s , size_t maxlen ) ;
void strnlen_constant0 ( ) {
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strnlen ( " 123 " , 10 ) = = 3 ) ; // expected-warning{{TRUE}}
2011-02-22 12:55:05 +08:00
}
void strnlen_constant1 ( ) {
const char * a = " 123 " ;
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strnlen ( a , 10 ) = = 3 ) ; // expected-warning{{TRUE}}
2011-02-22 12:55:05 +08:00
}
void strnlen_constant2 ( char x ) {
char a [ ] = " 123 " ;
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strnlen ( a , 10 ) = = 3 ) ; // expected-warning{{TRUE}}
2011-02-22 12:55:05 +08:00
a [ 0 ] = x ;
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strnlen ( a , 10 ) = = 3 ) ; // expected-warning{{UNKNOWN}}
2011-02-22 12:55:05 +08:00
}
void strnlen_constant4 ( ) {
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strnlen ( " 123456 " , 3 ) = = 3 ) ; // expected-warning{{TRUE}}
2011-02-22 12:55:05 +08:00
}
void strnlen_constant5 ( ) {
const char * a = " 123456 " ;
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strnlen ( a , 3 ) = = 3 ) ; // expected-warning{{TRUE}}
2011-02-22 12:55:05 +08:00
}
void strnlen_constant6 ( char x ) {
char a [ ] = " 123456 " ;
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strnlen ( a , 3 ) = = 3 ) ; // expected-warning{{TRUE}}
2011-02-22 12:55:05 +08:00
a [ 0 ] = x ;
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strnlen ( a , 3 ) = = 3 ) ; // expected-warning{{UNKNOWN}}
2011-02-22 12:55:05 +08:00
}
size_t strnlen_null ( ) {
2019-12-11 08:48:17 +08:00
return strnlen ( 0 , 3 ) ; // expected-warning{{Null pointer passed as 1st argument to string length function}}
2011-02-22 12:55:05 +08:00
}
size_t strnlen_fn ( ) {
2011-06-20 10:06:40 +08:00
return strnlen ( ( char * ) & strlen_fn , 3 ) ; // expected-warning{{Argument to string length function is the address of the function 'strlen_fn', which is not a null-terminated string}}
2011-02-22 12:55:05 +08:00
}
size_t strnlen_nonloc ( ) {
label :
2011-06-20 10:06:40 +08:00
return strnlen ( ( char * ) & & label , 3 ) ; // expected-warning{{Argument to string length function is the address of the label 'label', which is not a null-terminated string}}
2011-02-22 12:55:05 +08:00
}
2011-06-14 09:15:31 +08:00
void strnlen_zero ( ) {
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strnlen ( " abc " , 0 ) = = 0 ) ; // expected-warning{{TRUE}}
clang_analyzer_eval ( strnlen ( NULL , 0 ) = = 0 ) ; // expected-warning{{TRUE}}
2011-06-14 09:15:31 +08:00
}
2011-02-22 12:55:05 +08:00
2011-06-14 09:15:31 +08:00
size_t strnlen_compound_literal ( ) {
// This used to crash because we don't model the string lengths of
// compound literals.
return strnlen ( ( char [ ] ) { ' a ' , ' b ' , 0 } , 1 ) ;
}
2011-02-22 12:55:05 +08:00
2011-06-14 09:15:31 +08:00
size_t strnlen_unknown_limit ( float f ) {
// This used to crash because we don't model the integer values of floats.
return strnlen ( " abc " , ( int ) f ) ;
}
2011-02-22 12:55:05 +08:00
2011-06-14 09:15:31 +08:00
void strnlen_is_not_strlen ( char * x ) {
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strnlen ( x , 10 ) = = strlen ( x ) ) ; // expected-warning{{UNKNOWN}}
2011-02-22 12:55:05 +08:00
}
2011-06-14 09:15:31 +08:00
void strnlen_at_limit ( char * x ) {
size_t len = strnlen ( x , 10 ) ;
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( len < = 10 ) ; // expected-warning{{TRUE}}
clang_analyzer_eval ( len = = 10 ) ; // expected-warning{{UNKNOWN}}
clang_analyzer_eval ( len < 10 ) ; // expected-warning{{UNKNOWN}}
2011-02-22 12:55:05 +08:00
}
2011-06-14 09:15:31 +08:00
void strnlen_at_actual ( size_t limit ) {
size_t len = strnlen ( " abc " , limit ) ;
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( len < = 3 ) ; // expected-warning{{TRUE}}
// This is due to eager assertion in strnlen.
if ( limit = = 0 ) {
clang_analyzer_eval ( len = = 0 ) ; // expected-warning{{TRUE}}
} else {
clang_analyzer_eval ( len = = 3 ) ; // expected-warning{{UNKNOWN}}
clang_analyzer_eval ( len < 3 ) ; // expected-warning{{UNKNOWN}}
}
2011-02-22 12:55:05 +08:00
}
2010-08-16 15:51:42 +08:00
//===----------------------------------------------------------------------===
// strcpy()
//===----------------------------------------------------------------------===
# ifdef VARIANT
# define __strcpy_chk BUILTIN(__strcpy_chk)
char * __strcpy_chk ( char * restrict s1 , const char * restrict s2 , size_t destlen ) ;
# define strcpy(a,b) __strcpy_chk(a,b,(size_t)-1)
# else /* VARIANT */
# define strcpy BUILTIN(strcpy)
char * strcpy ( char * restrict s1 , const char * restrict s2 ) ;
# endif /* VARIANT */
void strcpy_null_dst ( char * x ) {
2019-12-11 08:48:17 +08:00
strcpy ( NULL , x ) ; // expected-warning{{Null pointer passed as 1st argument to string copy function}}
2010-08-16 15:51:42 +08:00
}
void strcpy_null_src ( char * x ) {
2019-12-11 08:48:17 +08:00
strcpy ( x , NULL ) ; // expected-warning{{Null pointer passed as 2nd argument to string copy function}}
2010-08-16 15:51:42 +08:00
}
void strcpy_fn ( char * x ) {
2011-06-20 10:06:40 +08:00
strcpy ( x , ( char * ) & strcpy_fn ) ; // expected-warning{{Argument to string copy function is the address of the function 'strcpy_fn', which is not a null-terminated string}}
2010-08-16 15:51:42 +08:00
}
2012-01-13 08:56:48 +08:00
void strcpy_fn_const ( char * x ) {
strcpy ( x , ( const char * ) & strcpy_fn ) ; // expected-warning{{Argument to string copy function is the address of the function 'strcpy_fn', which is not a null-terminated string}}
}
2013-03-21 04:36:01 +08:00
extern int globalInt ;
2010-08-16 15:51:42 +08:00
void strcpy_effects ( char * x , char * y ) {
char a = x [ 0 ] ;
2013-03-21 04:36:01 +08:00
if ( globalInt ! = 42 )
return ;
2010-08-16 15:51:42 +08:00
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strcpy ( x , y ) = = x ) ; // expected-warning{{TRUE}}
clang_analyzer_eval ( strlen ( x ) = = strlen ( y ) ) ; // expected-warning{{TRUE}}
clang_analyzer_eval ( a = = x [ 0 ] ) ; // expected-warning{{UNKNOWN}}
2013-03-21 04:36:01 +08:00
clang_analyzer_eval ( globalInt = = 42 ) ; // expected-warning{{TRUE}}
2010-08-16 15:51:42 +08:00
}
2018-07-13 21:44:44 +08:00
# ifndef SUPPRESS_OUT_OF_BOUND
2010-08-16 15:51:42 +08:00
void strcpy_overflow ( char * y ) {
char x [ 4 ] ;
if ( strlen ( y ) = = 4 )
[analyzer] NFCi: Refactor CStringChecker: use strongly typed internal API
Summary:
I wanted to extend the diagnostics of the CStringChecker with taintedness.
This requires the CStringChecker to be refactored to support a more flexible
reporting mechanism.
This patch does only refactorings, such:
- eliminates always false parameters (like WarnAboutSize)
- reduces the number of parameters
- makes strong types differentiating *source* and *destination* buffers
(same with size expressions)
- binds the argument expression and the index, making diagnostics accurate
and easy to emit
- removes a bunch of default parameters to make it more readable
- remove random const char* warning message parameters, making clear where
and what is going to be emitted
Note that:
- CheckBufferAccess now checks *only* one buffer, this removed about 100 LOC
code duplication
- not every function was refactored to use the /new/ strongly typed API, since
the CString related functions are really closely coupled monolithic beasts,
I will refactor them separately
- all tests are preserved and passing; only the message changed at some places.
In my opinion, these messages are holding the same information.
I would also highlight that this refactoring caught a bug in
clang/test/Analysis/string.c:454 where the diagnostic did not reflect reality.
This catch backs my effort on simplifying this monolithic CStringChecker.
Reviewers: NoQ, baloghadamsoftware, Szelethus, rengolin, Charusso
Reviewed By: NoQ
Subscribers: whisperity, xazax.hun, szepet, rnkovacs, a.sidorin,
mikhail.ramalho, donat.nagy, dkrupp, Charusso, martong, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D74806
2020-04-09 22:06:32 +08:00
strcpy ( x , y ) ; // expected-warning{{String copy function overflows the destination buffer}}
2010-08-16 15:51:42 +08:00
}
2018-07-13 21:44:44 +08:00
# endif
2010-08-16 15:51:42 +08:00
void strcpy_no_overflow ( char * y ) {
char x [ 4 ] ;
if ( strlen ( y ) = = 3 )
strcpy ( x , y ) ; // no-warning
}
2011-02-22 12:58:34 +08:00
//===----------------------------------------------------------------------===
2010-08-16 15:51:42 +08:00
// stpcpy()
//===----------------------------------------------------------------------===
# ifdef VARIANT
# define __stpcpy_chk BUILTIN(__stpcpy_chk)
char * __stpcpy_chk ( char * restrict s1 , const char * restrict s2 , size_t destlen ) ;
# define stpcpy(a,b) __stpcpy_chk(a,b,(size_t)-1)
# else /* VARIANT */
# define stpcpy BUILTIN(stpcpy)
char * stpcpy ( char * restrict s1 , const char * restrict s2 ) ;
# endif /* VARIANT */
void stpcpy_effect ( char * x , char * y ) {
char a = x [ 0 ] ;
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( stpcpy ( x , y ) = = & x [ strlen ( y ) ] ) ; // expected-warning{{TRUE}}
clang_analyzer_eval ( strlen ( x ) = = strlen ( y ) ) ; // expected-warning{{TRUE}}
clang_analyzer_eval ( a = = x [ 0 ] ) ; // expected-warning{{UNKNOWN}}
2010-08-16 15:51:42 +08:00
}
2018-07-13 21:44:44 +08:00
# ifndef SUPPRESS_OUT_OF_BOUND
2010-08-16 15:51:42 +08:00
void stpcpy_overflow ( char * y ) {
char x [ 4 ] ;
if ( strlen ( y ) = = 4 )
[analyzer] NFCi: Refactor CStringChecker: use strongly typed internal API
Summary:
I wanted to extend the diagnostics of the CStringChecker with taintedness.
This requires the CStringChecker to be refactored to support a more flexible
reporting mechanism.
This patch does only refactorings, such:
- eliminates always false parameters (like WarnAboutSize)
- reduces the number of parameters
- makes strong types differentiating *source* and *destination* buffers
(same with size expressions)
- binds the argument expression and the index, making diagnostics accurate
and easy to emit
- removes a bunch of default parameters to make it more readable
- remove random const char* warning message parameters, making clear where
and what is going to be emitted
Note that:
- CheckBufferAccess now checks *only* one buffer, this removed about 100 LOC
code duplication
- not every function was refactored to use the /new/ strongly typed API, since
the CString related functions are really closely coupled monolithic beasts,
I will refactor them separately
- all tests are preserved and passing; only the message changed at some places.
In my opinion, these messages are holding the same information.
I would also highlight that this refactoring caught a bug in
clang/test/Analysis/string.c:454 where the diagnostic did not reflect reality.
This catch backs my effort on simplifying this monolithic CStringChecker.
Reviewers: NoQ, baloghadamsoftware, Szelethus, rengolin, Charusso
Reviewed By: NoQ
Subscribers: whisperity, xazax.hun, szepet, rnkovacs, a.sidorin,
mikhail.ramalho, donat.nagy, dkrupp, Charusso, martong, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D74806
2020-04-09 22:06:32 +08:00
stpcpy ( x , y ) ; // expected-warning{{String copy function overflows the destination buffer}}
2010-08-16 15:51:42 +08:00
}
2018-07-13 21:44:44 +08:00
# endif
2010-08-16 15:51:42 +08:00
void stpcpy_no_overflow ( char * y ) {
char x [ 4 ] ;
if ( strlen ( y ) = = 3 )
stpcpy ( x , y ) ; // no-warning
}
2011-04-09 23:12:58 +08:00
//===----------------------------------------------------------------------===
// strcat()
//===----------------------------------------------------------------------===
# ifdef VARIANT
# define __strcat_chk BUILTIN(__strcat_chk)
char * __strcat_chk ( char * restrict s1 , const char * restrict s2 , size_t destlen ) ;
# define strcat(a,b) __strcat_chk(a,b,(size_t)-1)
# else /* VARIANT */
# define strcat BUILTIN(strcat)
char * strcat ( char * restrict s1 , const char * restrict s2 ) ;
# endif /* VARIANT */
void strcat_null_dst ( char * x ) {
2019-12-11 08:48:17 +08:00
strcat ( NULL , x ) ; // expected-warning{{Null pointer passed as 1st argument to string concatenation function}}
2011-04-09 23:12:58 +08:00
}
void strcat_null_src ( char * x ) {
2019-12-11 08:48:17 +08:00
strcat ( x , NULL ) ; // expected-warning{{Null pointer passed as 2nd argument to string concatenation function}}
2011-04-09 23:12:58 +08:00
}
void strcat_fn ( char * x ) {
2019-12-11 08:48:17 +08:00
strcat ( x , ( char * ) & strcat_fn ) ; // expected-warning{{Argument to string concatenation function is the address of the function 'strcat_fn', which is not a null-terminated string}}
2011-04-09 23:12:58 +08:00
}
void strcat_effects ( char * y ) {
char x [ 8 ] = " 123 " ;
size_t orig_len = strlen ( x ) ;
char a = x [ 0 ] ;
if ( strlen ( y ) ! = 4 )
return ;
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strcat ( x , y ) = = x ) ; // expected-warning{{TRUE}}
clang_analyzer_eval ( ( int ) strlen ( x ) = = ( orig_len + strlen ( y ) ) ) ; // expected-warning{{TRUE}}
2011-04-09 23:12:58 +08:00
}
2018-07-13 21:44:44 +08:00
# ifndef SUPPRESS_OUT_OF_BOUND
2011-04-09 23:12:58 +08:00
void strcat_overflow_0 ( char * y ) {
char x [ 4 ] = " 12 " ;
if ( strlen ( y ) = = 4 )
[analyzer] NFCi: Refactor CStringChecker: use strongly typed internal API
Summary:
I wanted to extend the diagnostics of the CStringChecker with taintedness.
This requires the CStringChecker to be refactored to support a more flexible
reporting mechanism.
This patch does only refactorings, such:
- eliminates always false parameters (like WarnAboutSize)
- reduces the number of parameters
- makes strong types differentiating *source* and *destination* buffers
(same with size expressions)
- binds the argument expression and the index, making diagnostics accurate
and easy to emit
- removes a bunch of default parameters to make it more readable
- remove random const char* warning message parameters, making clear where
and what is going to be emitted
Note that:
- CheckBufferAccess now checks *only* one buffer, this removed about 100 LOC
code duplication
- not every function was refactored to use the /new/ strongly typed API, since
the CString related functions are really closely coupled monolithic beasts,
I will refactor them separately
- all tests are preserved and passing; only the message changed at some places.
In my opinion, these messages are holding the same information.
I would also highlight that this refactoring caught a bug in
clang/test/Analysis/string.c:454 where the diagnostic did not reflect reality.
This catch backs my effort on simplifying this monolithic CStringChecker.
Reviewers: NoQ, baloghadamsoftware, Szelethus, rengolin, Charusso
Reviewed By: NoQ
Subscribers: whisperity, xazax.hun, szepet, rnkovacs, a.sidorin,
mikhail.ramalho, donat.nagy, dkrupp, Charusso, martong, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D74806
2020-04-09 22:06:32 +08:00
strcat ( x , y ) ; // expected-warning{{String concatenation function overflows the destination buffer}}
2011-04-09 23:12:58 +08:00
}
void strcat_overflow_1 ( char * y ) {
char x [ 4 ] = " 12 " ;
if ( strlen ( y ) = = 3 )
[analyzer] NFCi: Refactor CStringChecker: use strongly typed internal API
Summary:
I wanted to extend the diagnostics of the CStringChecker with taintedness.
This requires the CStringChecker to be refactored to support a more flexible
reporting mechanism.
This patch does only refactorings, such:
- eliminates always false parameters (like WarnAboutSize)
- reduces the number of parameters
- makes strong types differentiating *source* and *destination* buffers
(same with size expressions)
- binds the argument expression and the index, making diagnostics accurate
and easy to emit
- removes a bunch of default parameters to make it more readable
- remove random const char* warning message parameters, making clear where
and what is going to be emitted
Note that:
- CheckBufferAccess now checks *only* one buffer, this removed about 100 LOC
code duplication
- not every function was refactored to use the /new/ strongly typed API, since
the CString related functions are really closely coupled monolithic beasts,
I will refactor them separately
- all tests are preserved and passing; only the message changed at some places.
In my opinion, these messages are holding the same information.
I would also highlight that this refactoring caught a bug in
clang/test/Analysis/string.c:454 where the diagnostic did not reflect reality.
This catch backs my effort on simplifying this monolithic CStringChecker.
Reviewers: NoQ, baloghadamsoftware, Szelethus, rengolin, Charusso
Reviewed By: NoQ
Subscribers: whisperity, xazax.hun, szepet, rnkovacs, a.sidorin,
mikhail.ramalho, donat.nagy, dkrupp, Charusso, martong, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D74806
2020-04-09 22:06:32 +08:00
strcat ( x , y ) ; // expected-warning{{String concatenation function overflows the destination buffer}}
2011-04-09 23:12:58 +08:00
}
void strcat_overflow_2 ( char * y ) {
char x [ 4 ] = " 12 " ;
if ( strlen ( y ) = = 2 )
[analyzer] NFCi: Refactor CStringChecker: use strongly typed internal API
Summary:
I wanted to extend the diagnostics of the CStringChecker with taintedness.
This requires the CStringChecker to be refactored to support a more flexible
reporting mechanism.
This patch does only refactorings, such:
- eliminates always false parameters (like WarnAboutSize)
- reduces the number of parameters
- makes strong types differentiating *source* and *destination* buffers
(same with size expressions)
- binds the argument expression and the index, making diagnostics accurate
and easy to emit
- removes a bunch of default parameters to make it more readable
- remove random const char* warning message parameters, making clear where
and what is going to be emitted
Note that:
- CheckBufferAccess now checks *only* one buffer, this removed about 100 LOC
code duplication
- not every function was refactored to use the /new/ strongly typed API, since
the CString related functions are really closely coupled monolithic beasts,
I will refactor them separately
- all tests are preserved and passing; only the message changed at some places.
In my opinion, these messages are holding the same information.
I would also highlight that this refactoring caught a bug in
clang/test/Analysis/string.c:454 where the diagnostic did not reflect reality.
This catch backs my effort on simplifying this monolithic CStringChecker.
Reviewers: NoQ, baloghadamsoftware, Szelethus, rengolin, Charusso
Reviewed By: NoQ
Subscribers: whisperity, xazax.hun, szepet, rnkovacs, a.sidorin,
mikhail.ramalho, donat.nagy, dkrupp, Charusso, martong, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D74806
2020-04-09 22:06:32 +08:00
strcat ( x , y ) ; // expected-warning{{String concatenation function overflows the destination buffer}}
2011-04-09 23:12:58 +08:00
}
2018-07-13 21:44:44 +08:00
# endif
2011-04-09 23:12:58 +08:00
void strcat_no_overflow ( char * y ) {
char x [ 5 ] = " 12 " ;
if ( strlen ( y ) = = 2 )
strcat ( x , y ) ; // no-warning
}
2011-06-15 13:52:56 +08:00
void strcat_symbolic_dst_length ( char * dst ) {
strcat ( dst , " 1234 " ) ;
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strlen ( dst ) > = 4 ) ; // expected-warning{{TRUE}}
2011-06-15 13:52:56 +08:00
}
2011-12-12 02:43:40 +08:00
void strcat_symbolic_dst_length_taint ( char * dst ) {
scanf ( " %s " , dst ) ; // Taint data.
strcat ( dst , " 1234 " ) ;
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strlen ( dst ) > = 4 ) ; // expected-warning{{TRUE}}
2011-12-12 02:43:40 +08:00
}
2011-06-15 13:52:56 +08:00
void strcat_unknown_src_length ( char * src , int offset ) {
char dst [ 8 ] = " 1234 " ;
strcat ( dst , & src [ offset ] ) ;
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strlen ( dst ) > = 4 ) ; // expected-warning{{TRUE}}
2011-06-15 13:52:56 +08:00
}
// There is no strcat_unknown_dst_length because if we can't get a symbolic
// length for the "before" strlen, we won't be able to set one for "after".
void strcat_too_big ( char * dst , char * src ) {
2013-08-20 00:27:34 +08:00
// We assume this can never actually happen, so we don't get a warning.
2011-06-15 13:52:56 +08:00
if ( strlen ( dst ) ! = ( ( ( size_t ) 0 ) - 2 ) )
return ;
if ( strlen ( src ) ! = 2 )
return ;
2013-08-20 00:27:34 +08:00
strcat ( dst , src ) ;
2011-06-15 13:52:56 +08:00
}
2011-04-09 23:12:58 +08:00
2011-06-20 11:49:16 +08:00
//===----------------------------------------------------------------------===
// strncpy()
//===----------------------------------------------------------------------===
# ifdef VARIANT
# define __strncpy_chk BUILTIN(__strncpy_chk)
char * __strncpy_chk ( char * restrict s1 , const char * restrict s2 , size_t n , size_t destlen ) ;
# define strncpy(a,b,n) __strncpy_chk(a,b,n,(size_t)-1)
# else /* VARIANT */
# define strncpy BUILTIN(strncpy)
char * strncpy ( char * restrict s1 , const char * restrict s2 , size_t n ) ;
# endif /* VARIANT */
void strncpy_null_dst ( char * x ) {
2019-12-11 08:48:17 +08:00
strncpy ( NULL , x , 5 ) ; // expected-warning{{Null pointer passed as 1st argument to string copy function}}
2011-06-20 11:49:16 +08:00
}
void strncpy_null_src ( char * x ) {
2019-12-11 08:48:17 +08:00
strncpy ( x , NULL , 5 ) ; // expected-warning{{Null pointer passed as 2nd argument to string copy function}}
2011-06-20 11:49:16 +08:00
}
void strncpy_fn ( char * x ) {
strncpy ( x , ( char * ) & strcpy_fn , 5 ) ; // expected-warning{{Argument to string copy function is the address of the function 'strcpy_fn', which is not a null-terminated string}}
}
void strncpy_effects ( char * x , char * y ) {
char a = x [ 0 ] ;
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strncpy ( x , y , 5 ) = = x ) ; // expected-warning{{TRUE}}
clang_analyzer_eval ( strlen ( x ) = = strlen ( y ) ) ; // expected-warning{{UNKNOWN}}
clang_analyzer_eval ( a = = x [ 0 ] ) ; // expected-warning{{UNKNOWN}}
2011-06-20 11:49:16 +08:00
}
2018-07-13 21:44:44 +08:00
# ifndef SUPPRESS_OUT_OF_BOUND
// Enabling the malloc checker enables some of the buffer-checking portions
// of the C-string checker.
void cstringchecker_bounds_nocrash ( ) {
char * p = malloc ( 2 ) ;
[analyzer] NFCi: Refactor CStringChecker: use strongly typed internal API
Summary:
I wanted to extend the diagnostics of the CStringChecker with taintedness.
This requires the CStringChecker to be refactored to support a more flexible
reporting mechanism.
This patch does only refactorings, such:
- eliminates always false parameters (like WarnAboutSize)
- reduces the number of parameters
- makes strong types differentiating *source* and *destination* buffers
(same with size expressions)
- binds the argument expression and the index, making diagnostics accurate
and easy to emit
- removes a bunch of default parameters to make it more readable
- remove random const char* warning message parameters, making clear where
and what is going to be emitted
Note that:
- CheckBufferAccess now checks *only* one buffer, this removed about 100 LOC
code duplication
- not every function was refactored to use the /new/ strongly typed API, since
the CString related functions are really closely coupled monolithic beasts,
I will refactor them separately
- all tests are preserved and passing; only the message changed at some places.
In my opinion, these messages are holding the same information.
I would also highlight that this refactoring caught a bug in
clang/test/Analysis/string.c:454 where the diagnostic did not reflect reality.
This catch backs my effort on simplifying this monolithic CStringChecker.
Reviewers: NoQ, baloghadamsoftware, Szelethus, rengolin, Charusso
Reviewed By: NoQ
Subscribers: whisperity, xazax.hun, szepet, rnkovacs, a.sidorin,
mikhail.ramalho, donat.nagy, dkrupp, Charusso, martong, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D74806
2020-04-09 22:06:32 +08:00
strncpy ( p , " AAA " , sizeof ( " AAA " ) ) ;
// expected-warning@-1 {{String copy function overflows the destination buffer}}
2018-07-13 21:44:44 +08:00
free ( p ) ;
}
2011-06-20 11:49:16 +08:00
void strncpy_overflow ( char * y ) {
char x [ 4 ] ;
if ( strlen ( y ) = = 4 )
[analyzer] NFCi: Refactor CStringChecker: use strongly typed internal API
Summary:
I wanted to extend the diagnostics of the CStringChecker with taintedness.
This requires the CStringChecker to be refactored to support a more flexible
reporting mechanism.
This patch does only refactorings, such:
- eliminates always false parameters (like WarnAboutSize)
- reduces the number of parameters
- makes strong types differentiating *source* and *destination* buffers
(same with size expressions)
- binds the argument expression and the index, making diagnostics accurate
and easy to emit
- removes a bunch of default parameters to make it more readable
- remove random const char* warning message parameters, making clear where
and what is going to be emitted
Note that:
- CheckBufferAccess now checks *only* one buffer, this removed about 100 LOC
code duplication
- not every function was refactored to use the /new/ strongly typed API, since
the CString related functions are really closely coupled monolithic beasts,
I will refactor them separately
- all tests are preserved and passing; only the message changed at some places.
In my opinion, these messages are holding the same information.
I would also highlight that this refactoring caught a bug in
clang/test/Analysis/string.c:454 where the diagnostic did not reflect reality.
This catch backs my effort on simplifying this monolithic CStringChecker.
Reviewers: NoQ, baloghadamsoftware, Szelethus, rengolin, Charusso
Reviewed By: NoQ
Subscribers: whisperity, xazax.hun, szepet, rnkovacs, a.sidorin,
mikhail.ramalho, donat.nagy, dkrupp, Charusso, martong, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D74806
2020-04-09 22:06:32 +08:00
strncpy ( x , y , 5 ) ;
// expected-warning@-1 {{String copy function overflows the destination buffer}}
2019-03-19 03:23:45 +08:00
# ifndef VARIANT
[analyzer] NFCi: Refactor CStringChecker: use strongly typed internal API
Summary:
I wanted to extend the diagnostics of the CStringChecker with taintedness.
This requires the CStringChecker to be refactored to support a more flexible
reporting mechanism.
This patch does only refactorings, such:
- eliminates always false parameters (like WarnAboutSize)
- reduces the number of parameters
- makes strong types differentiating *source* and *destination* buffers
(same with size expressions)
- binds the argument expression and the index, making diagnostics accurate
and easy to emit
- removes a bunch of default parameters to make it more readable
- remove random const char* warning message parameters, making clear where
and what is going to be emitted
Note that:
- CheckBufferAccess now checks *only* one buffer, this removed about 100 LOC
code duplication
- not every function was refactored to use the /new/ strongly typed API, since
the CString related functions are really closely coupled monolithic beasts,
I will refactor them separately
- all tests are preserved and passing; only the message changed at some places.
In my opinion, these messages are holding the same information.
I would also highlight that this refactoring caught a bug in
clang/test/Analysis/string.c:454 where the diagnostic did not reflect reality.
This catch backs my effort on simplifying this monolithic CStringChecker.
Reviewers: NoQ, baloghadamsoftware, Szelethus, rengolin, Charusso
Reviewed By: NoQ
Subscribers: whisperity, xazax.hun, szepet, rnkovacs, a.sidorin,
mikhail.ramalho, donat.nagy, dkrupp, Charusso, martong, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D74806
2020-04-09 22:06:32 +08:00
// expected-warning@-3 {{size argument is too large; destination buffer has size 4, but size argument is 5}}
2019-03-19 03:23:45 +08:00
# endif
2011-06-20 11:49:16 +08:00
}
void strncpy_no_overflow ( char * y ) {
char x [ 4 ] ;
if ( strlen ( y ) = = 3 )
[analyzer] NFCi: Refactor CStringChecker: use strongly typed internal API
Summary:
I wanted to extend the diagnostics of the CStringChecker with taintedness.
This requires the CStringChecker to be refactored to support a more flexible
reporting mechanism.
This patch does only refactorings, such:
- eliminates always false parameters (like WarnAboutSize)
- reduces the number of parameters
- makes strong types differentiating *source* and *destination* buffers
(same with size expressions)
- binds the argument expression and the index, making diagnostics accurate
and easy to emit
- removes a bunch of default parameters to make it more readable
- remove random const char* warning message parameters, making clear where
and what is going to be emitted
Note that:
- CheckBufferAccess now checks *only* one buffer, this removed about 100 LOC
code duplication
- not every function was refactored to use the /new/ strongly typed API, since
the CString related functions are really closely coupled monolithic beasts,
I will refactor them separately
- all tests are preserved and passing; only the message changed at some places.
In my opinion, these messages are holding the same information.
I would also highlight that this refactoring caught a bug in
clang/test/Analysis/string.c:454 where the diagnostic did not reflect reality.
This catch backs my effort on simplifying this monolithic CStringChecker.
Reviewers: NoQ, baloghadamsoftware, Szelethus, rengolin, Charusso
Reviewed By: NoQ
Subscribers: whisperity, xazax.hun, szepet, rnkovacs, a.sidorin,
mikhail.ramalho, donat.nagy, dkrupp, Charusso, martong, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D74806
2020-04-09 22:06:32 +08:00
strncpy ( x , y , 5 ) ;
// expected-warning@-1 {{String copy function overflows the destination buffer}}
2019-03-19 03:23:45 +08:00
# ifndef VARIANT
[analyzer] NFCi: Refactor CStringChecker: use strongly typed internal API
Summary:
I wanted to extend the diagnostics of the CStringChecker with taintedness.
This requires the CStringChecker to be refactored to support a more flexible
reporting mechanism.
This patch does only refactorings, such:
- eliminates always false parameters (like WarnAboutSize)
- reduces the number of parameters
- makes strong types differentiating *source* and *destination* buffers
(same with size expressions)
- binds the argument expression and the index, making diagnostics accurate
and easy to emit
- removes a bunch of default parameters to make it more readable
- remove random const char* warning message parameters, making clear where
and what is going to be emitted
Note that:
- CheckBufferAccess now checks *only* one buffer, this removed about 100 LOC
code duplication
- not every function was refactored to use the /new/ strongly typed API, since
the CString related functions are really closely coupled monolithic beasts,
I will refactor them separately
- all tests are preserved and passing; only the message changed at some places.
In my opinion, these messages are holding the same information.
I would also highlight that this refactoring caught a bug in
clang/test/Analysis/string.c:454 where the diagnostic did not reflect reality.
This catch backs my effort on simplifying this monolithic CStringChecker.
Reviewers: NoQ, baloghadamsoftware, Szelethus, rengolin, Charusso
Reviewed By: NoQ
Subscribers: whisperity, xazax.hun, szepet, rnkovacs, a.sidorin,
mikhail.ramalho, donat.nagy, dkrupp, Charusso, martong, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D74806
2020-04-09 22:06:32 +08:00
// expected-warning@-3 {{size argument is too large; destination buffer has size 4, but size argument is 5}}
2019-03-19 03:23:45 +08:00
# endif
2011-06-20 11:49:16 +08:00
}
void strncpy_no_overflow2 ( char * y , int n ) {
if ( n < = 4 )
return ;
char x [ 4 ] ;
if ( strlen ( y ) = = 3 )
[analyzer] NFCi: Refactor CStringChecker: use strongly typed internal API
Summary:
I wanted to extend the diagnostics of the CStringChecker with taintedness.
This requires the CStringChecker to be refactored to support a more flexible
reporting mechanism.
This patch does only refactorings, such:
- eliminates always false parameters (like WarnAboutSize)
- reduces the number of parameters
- makes strong types differentiating *source* and *destination* buffers
(same with size expressions)
- binds the argument expression and the index, making diagnostics accurate
and easy to emit
- removes a bunch of default parameters to make it more readable
- remove random const char* warning message parameters, making clear where
and what is going to be emitted
Note that:
- CheckBufferAccess now checks *only* one buffer, this removed about 100 LOC
code duplication
- not every function was refactored to use the /new/ strongly typed API, since
the CString related functions are really closely coupled monolithic beasts,
I will refactor them separately
- all tests are preserved and passing; only the message changed at some places.
In my opinion, these messages are holding the same information.
I would also highlight that this refactoring caught a bug in
clang/test/Analysis/string.c:454 where the diagnostic did not reflect reality.
This catch backs my effort on simplifying this monolithic CStringChecker.
Reviewers: NoQ, baloghadamsoftware, Szelethus, rengolin, Charusso
Reviewed By: NoQ
Subscribers: whisperity, xazax.hun, szepet, rnkovacs, a.sidorin,
mikhail.ramalho, donat.nagy, dkrupp, Charusso, martong, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D74806
2020-04-09 22:06:32 +08:00
strncpy ( x , y , n ) ;
// expected-warning@-1 {{String copy function overflows the destination buffer}}
2011-06-20 11:49:16 +08:00
}
2018-07-13 21:44:44 +08:00
# endif
2011-06-20 11:49:16 +08:00
void strncpy_truncate ( char * y ) {
char x [ 4 ] ;
if ( strlen ( y ) = = 4 )
strncpy ( x , y , 3 ) ; // no-warning
}
void strncpy_no_truncate ( char * y ) {
char x [ 4 ] ;
if ( strlen ( y ) = = 3 )
strncpy ( x , y , 3 ) ; // no-warning
}
void strncpy_exactly_matching_buffer ( char * y ) {
char x [ 4 ] ;
strncpy ( x , y , 4 ) ; // no-warning
// strncpy does not null-terminate, so we have no idea what the strlen is
// after this.
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strlen ( x ) > 4 ) ; // expected-warning{{UNKNOWN}}
2011-06-20 11:49:16 +08:00
}
2012-05-15 01:58:35 +08:00
void strncpy_zero ( char * src ) {
char dst [ ] = " 123 " ;
strncpy ( dst , src , 0 ) ; // no-warning
}
void strncpy_empty ( ) {
char dst [ ] = " 123 " ;
char src [ ] = " " ;
strncpy ( dst , src , 4 ) ; // no-warning
}
2011-04-09 23:12:58 +08:00
//===----------------------------------------------------------------------===
// strncat()
//===----------------------------------------------------------------------===
# ifdef VARIANT
# define __strncat_chk BUILTIN(__strncat_chk)
char * __strncat_chk ( char * restrict s1 , const char * restrict s2 , size_t n , size_t destlen ) ;
# define strncat(a,b,c) __strncat_chk(a,b,c, (size_t)-1)
# else /* VARIANT */
# define strncat BUILTIN(strncat)
char * strncat ( char * restrict s1 , const char * restrict s2 , size_t n ) ;
# endif /* VARIANT */
void strncat_null_dst ( char * x ) {
2019-12-11 08:48:17 +08:00
strncat ( NULL , x , 4 ) ; // expected-warning{{Null pointer passed as 1st argument to string concatenation function}}
2011-04-09 23:12:58 +08:00
}
void strncat_null_src ( char * x ) {
2019-12-11 08:48:17 +08:00
strncat ( x , NULL , 4 ) ; // expected-warning{{Null pointer passed as 2nd argument to string concatenation function}}
2011-04-09 23:12:58 +08:00
}
void strncat_fn ( char * x ) {
2019-12-11 08:48:17 +08:00
strncat ( x , ( char * ) & strncat_fn , 4 ) ; // expected-warning{{Argument to string concatenation function is the address of the function 'strncat_fn', which is not a null-terminated string}}
2011-04-09 23:12:58 +08:00
}
void strncat_effects ( char * y ) {
char x [ 8 ] = " 123 " ;
size_t orig_len = strlen ( x ) ;
char a = x [ 0 ] ;
if ( strlen ( y ) ! = 4 )
return ;
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strncat ( x , y , strlen ( y ) ) = = x ) ; // expected-warning{{TRUE}}
clang_analyzer_eval ( strlen ( x ) = = ( orig_len + strlen ( y ) ) ) ; // expected-warning{{TRUE}}
2011-04-09 23:12:58 +08:00
}
2018-07-13 21:44:44 +08:00
# ifndef SUPPRESS_OUT_OF_BOUND
2011-04-09 23:12:58 +08:00
void strncat_overflow_0 ( char * y ) {
char x [ 4 ] = " 12 " ;
if ( strlen ( y ) = = 4 )
[analyzer] NFCi: Refactor CStringChecker: use strongly typed internal API
Summary:
I wanted to extend the diagnostics of the CStringChecker with taintedness.
This requires the CStringChecker to be refactored to support a more flexible
reporting mechanism.
This patch does only refactorings, such:
- eliminates always false parameters (like WarnAboutSize)
- reduces the number of parameters
- makes strong types differentiating *source* and *destination* buffers
(same with size expressions)
- binds the argument expression and the index, making diagnostics accurate
and easy to emit
- removes a bunch of default parameters to make it more readable
- remove random const char* warning message parameters, making clear where
and what is going to be emitted
Note that:
- CheckBufferAccess now checks *only* one buffer, this removed about 100 LOC
code duplication
- not every function was refactored to use the /new/ strongly typed API, since
the CString related functions are really closely coupled monolithic beasts,
I will refactor them separately
- all tests are preserved and passing; only the message changed at some places.
In my opinion, these messages are holding the same information.
I would also highlight that this refactoring caught a bug in
clang/test/Analysis/string.c:454 where the diagnostic did not reflect reality.
This catch backs my effort on simplifying this monolithic CStringChecker.
Reviewers: NoQ, baloghadamsoftware, Szelethus, rengolin, Charusso
Reviewed By: NoQ
Subscribers: whisperity, xazax.hun, szepet, rnkovacs, a.sidorin,
mikhail.ramalho, donat.nagy, dkrupp, Charusso, martong, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D74806
2020-04-09 22:06:32 +08:00
strncat ( x , y , strlen ( y ) ) ;
// expected-warning@-1 {{String concatenation function overflows the destination buffer}}
2011-04-09 23:12:58 +08:00
}
void strncat_overflow_1 ( char * y ) {
char x [ 4 ] = " 12 " ;
if ( strlen ( y ) = = 3 )
[analyzer] NFCi: Refactor CStringChecker: use strongly typed internal API
Summary:
I wanted to extend the diagnostics of the CStringChecker with taintedness.
This requires the CStringChecker to be refactored to support a more flexible
reporting mechanism.
This patch does only refactorings, such:
- eliminates always false parameters (like WarnAboutSize)
- reduces the number of parameters
- makes strong types differentiating *source* and *destination* buffers
(same with size expressions)
- binds the argument expression and the index, making diagnostics accurate
and easy to emit
- removes a bunch of default parameters to make it more readable
- remove random const char* warning message parameters, making clear where
and what is going to be emitted
Note that:
- CheckBufferAccess now checks *only* one buffer, this removed about 100 LOC
code duplication
- not every function was refactored to use the /new/ strongly typed API, since
the CString related functions are really closely coupled monolithic beasts,
I will refactor them separately
- all tests are preserved and passing; only the message changed at some places.
In my opinion, these messages are holding the same information.
I would also highlight that this refactoring caught a bug in
clang/test/Analysis/string.c:454 where the diagnostic did not reflect reality.
This catch backs my effort on simplifying this monolithic CStringChecker.
Reviewers: NoQ, baloghadamsoftware, Szelethus, rengolin, Charusso
Reviewed By: NoQ
Subscribers: whisperity, xazax.hun, szepet, rnkovacs, a.sidorin,
mikhail.ramalho, donat.nagy, dkrupp, Charusso, martong, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D74806
2020-04-09 22:06:32 +08:00
strncat ( x , y , strlen ( y ) ) ;
// expected-warning@-1 {{String concatenation function overflows the destination buffer}}
2011-04-09 23:12:58 +08:00
}
void strncat_overflow_2 ( char * y ) {
char x [ 4 ] = " 12 " ;
if ( strlen ( y ) = = 2 )
[analyzer] NFCi: Refactor CStringChecker: use strongly typed internal API
Summary:
I wanted to extend the diagnostics of the CStringChecker with taintedness.
This requires the CStringChecker to be refactored to support a more flexible
reporting mechanism.
This patch does only refactorings, such:
- eliminates always false parameters (like WarnAboutSize)
- reduces the number of parameters
- makes strong types differentiating *source* and *destination* buffers
(same with size expressions)
- binds the argument expression and the index, making diagnostics accurate
and easy to emit
- removes a bunch of default parameters to make it more readable
- remove random const char* warning message parameters, making clear where
and what is going to be emitted
Note that:
- CheckBufferAccess now checks *only* one buffer, this removed about 100 LOC
code duplication
- not every function was refactored to use the /new/ strongly typed API, since
the CString related functions are really closely coupled monolithic beasts,
I will refactor them separately
- all tests are preserved and passing; only the message changed at some places.
In my opinion, these messages are holding the same information.
I would also highlight that this refactoring caught a bug in
clang/test/Analysis/string.c:454 where the diagnostic did not reflect reality.
This catch backs my effort on simplifying this monolithic CStringChecker.
Reviewers: NoQ, baloghadamsoftware, Szelethus, rengolin, Charusso
Reviewed By: NoQ
Subscribers: whisperity, xazax.hun, szepet, rnkovacs, a.sidorin,
mikhail.ramalho, donat.nagy, dkrupp, Charusso, martong, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D74806
2020-04-09 22:06:32 +08:00
strncat ( x , y , strlen ( y ) ) ;
// expected-warning@-1 {{String concatenation function overflows the destination buffer}}
2011-04-09 23:12:58 +08:00
}
void strncat_overflow_3 ( char * y ) {
char x [ 4 ] = " 12 " ;
if ( strlen ( y ) = = 4 )
[analyzer] NFCi: Refactor CStringChecker: use strongly typed internal API
Summary:
I wanted to extend the diagnostics of the CStringChecker with taintedness.
This requires the CStringChecker to be refactored to support a more flexible
reporting mechanism.
This patch does only refactorings, such:
- eliminates always false parameters (like WarnAboutSize)
- reduces the number of parameters
- makes strong types differentiating *source* and *destination* buffers
(same with size expressions)
- binds the argument expression and the index, making diagnostics accurate
and easy to emit
- removes a bunch of default parameters to make it more readable
- remove random const char* warning message parameters, making clear where
and what is going to be emitted
Note that:
- CheckBufferAccess now checks *only* one buffer, this removed about 100 LOC
code duplication
- not every function was refactored to use the /new/ strongly typed API, since
the CString related functions are really closely coupled monolithic beasts,
I will refactor them separately
- all tests are preserved and passing; only the message changed at some places.
In my opinion, these messages are holding the same information.
I would also highlight that this refactoring caught a bug in
clang/test/Analysis/string.c:454 where the diagnostic did not reflect reality.
This catch backs my effort on simplifying this monolithic CStringChecker.
Reviewers: NoQ, baloghadamsoftware, Szelethus, rengolin, Charusso
Reviewed By: NoQ
Subscribers: whisperity, xazax.hun, szepet, rnkovacs, a.sidorin,
mikhail.ramalho, donat.nagy, dkrupp, Charusso, martong, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D74806
2020-04-09 22:06:32 +08:00
strncat ( x , y , 2 ) ;
// expected-warning@-1 {{String concatenation function overflows the destination buffer}}
2011-04-09 23:12:58 +08:00
}
2018-07-13 21:44:44 +08:00
# endif
2011-04-09 23:12:58 +08:00
void strncat_no_overflow_1 ( char * y ) {
char x [ 5 ] = " 12 " ;
if ( strlen ( y ) = = 2 )
strncat ( x , y , strlen ( y ) ) ; // no-warning
}
void strncat_no_overflow_2 ( char * y ) {
char x [ 4 ] = " 12 " ;
if ( strlen ( y ) = = 4 )
strncat ( x , y , 1 ) ; // no-warning
}
2011-04-13 01:08:43 +08:00
2011-06-21 05:55:40 +08:00
void strncat_symbolic_dst_length ( char * dst ) {
strncat ( dst , " 1234 " , 5 ) ;
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strlen ( dst ) > = 4 ) ; // expected-warning{{TRUE}}
2011-06-21 05:55:40 +08:00
}
2018-07-13 21:44:44 +08:00
# ifndef SUPPRESS_OUT_OF_BOUND
2011-06-21 05:55:40 +08:00
void strncat_symbolic_src_length ( char * src ) {
char dst [ 8 ] = " 1234 " ;
strncat ( dst , src , 3 ) ;
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strlen ( dst ) > = 4 ) ; // expected-warning{{TRUE}}
2011-06-21 05:55:40 +08:00
char dst2 [ 8 ] = " 1234 " ;
[analyzer] NFCi: Refactor CStringChecker: use strongly typed internal API
Summary:
I wanted to extend the diagnostics of the CStringChecker with taintedness.
This requires the CStringChecker to be refactored to support a more flexible
reporting mechanism.
This patch does only refactorings, such:
- eliminates always false parameters (like WarnAboutSize)
- reduces the number of parameters
- makes strong types differentiating *source* and *destination* buffers
(same with size expressions)
- binds the argument expression and the index, making diagnostics accurate
and easy to emit
- removes a bunch of default parameters to make it more readable
- remove random const char* warning message parameters, making clear where
and what is going to be emitted
Note that:
- CheckBufferAccess now checks *only* one buffer, this removed about 100 LOC
code duplication
- not every function was refactored to use the /new/ strongly typed API, since
the CString related functions are really closely coupled monolithic beasts,
I will refactor them separately
- all tests are preserved and passing; only the message changed at some places.
In my opinion, these messages are holding the same information.
I would also highlight that this refactoring caught a bug in
clang/test/Analysis/string.c:454 where the diagnostic did not reflect reality.
This catch backs my effort on simplifying this monolithic CStringChecker.
Reviewers: NoQ, baloghadamsoftware, Szelethus, rengolin, Charusso
Reviewed By: NoQ
Subscribers: whisperity, xazax.hun, szepet, rnkovacs, a.sidorin,
mikhail.ramalho, donat.nagy, dkrupp, Charusso, martong, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D74806
2020-04-09 22:06:32 +08:00
strncat ( dst2 , src , 4 ) ;
// expected-warning@-1 {{String concatenation function overflows the destination buffer}}
2011-06-21 05:55:40 +08:00
}
void strncat_unknown_src_length ( char * src , int offset ) {
char dst [ 8 ] = " 1234 " ;
strncat ( dst , & src [ offset ] , 3 ) ;
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strlen ( dst ) > = 4 ) ; // expected-warning{{TRUE}}
2011-06-21 05:55:40 +08:00
char dst2 [ 8 ] = " 1234 " ;
[analyzer] NFCi: Refactor CStringChecker: use strongly typed internal API
Summary:
I wanted to extend the diagnostics of the CStringChecker with taintedness.
This requires the CStringChecker to be refactored to support a more flexible
reporting mechanism.
This patch does only refactorings, such:
- eliminates always false parameters (like WarnAboutSize)
- reduces the number of parameters
- makes strong types differentiating *source* and *destination* buffers
(same with size expressions)
- binds the argument expression and the index, making diagnostics accurate
and easy to emit
- removes a bunch of default parameters to make it more readable
- remove random const char* warning message parameters, making clear where
and what is going to be emitted
Note that:
- CheckBufferAccess now checks *only* one buffer, this removed about 100 LOC
code duplication
- not every function was refactored to use the /new/ strongly typed API, since
the CString related functions are really closely coupled monolithic beasts,
I will refactor them separately
- all tests are preserved and passing; only the message changed at some places.
In my opinion, these messages are holding the same information.
I would also highlight that this refactoring caught a bug in
clang/test/Analysis/string.c:454 where the diagnostic did not reflect reality.
This catch backs my effort on simplifying this monolithic CStringChecker.
Reviewers: NoQ, baloghadamsoftware, Szelethus, rengolin, Charusso
Reviewed By: NoQ
Subscribers: whisperity, xazax.hun, szepet, rnkovacs, a.sidorin,
mikhail.ramalho, donat.nagy, dkrupp, Charusso, martong, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D74806
2020-04-09 22:06:32 +08:00
strncat ( dst2 , & src [ offset ] , 4 ) ;
// expected-warning@-1 {{String concatenation function overflows the destination buffer}}
2011-06-21 05:55:40 +08:00
}
2018-07-13 21:44:44 +08:00
# endif
2011-06-21 05:55:40 +08:00
// There is no strncat_unknown_dst_length because if we can't get a symbolic
// length for the "before" strlen, we won't be able to set one for "after".
void strncat_symbolic_limit ( unsigned limit ) {
char dst [ 6 ] = " 1234 " ;
char src [ ] = " 567 " ;
strncat ( dst , src , limit ) ; // no-warning
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strlen ( dst ) > = 4 ) ; // expected-warning{{TRUE}}
clang_analyzer_eval ( strlen ( dst ) = = 4 ) ; // expected-warning{{UNKNOWN}}
2011-06-21 05:55:40 +08:00
}
void strncat_unknown_limit ( float limit ) {
char dst [ 6 ] = " 1234 " ;
char src [ ] = " 567 " ;
strncat ( dst , src , ( size_t ) limit ) ; // no-warning
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strlen ( dst ) > = 4 ) ; // expected-warning{{TRUE}}
clang_analyzer_eval ( strlen ( dst ) = = 4 ) ; // expected-warning{{UNKNOWN}}
2011-06-21 05:55:40 +08:00
}
void strncat_too_big ( char * dst , char * src ) {
2013-08-20 00:27:34 +08:00
// We assume this will never actually happen, so we don't get a warning.
2011-06-21 05:55:40 +08:00
if ( strlen ( dst ) ! = ( ( ( size_t ) 0 ) - 2 ) )
return ;
if ( strlen ( src ) ! = 2 )
return ;
2013-08-20 00:27:34 +08:00
strncat ( dst , src , 2 ) ;
2011-06-21 05:55:40 +08:00
}
2012-05-15 01:58:35 +08:00
void strncat_zero ( char * src ) {
char dst [ ] = " 123 " ;
strncat ( dst , src , 0 ) ; // no-warning
}
void strncat_empty ( ) {
char dst [ 8 ] = " 123 " ;
char src [ ] = " " ;
strncat ( dst , src , 4 ) ; // no-warning
}
2011-04-13 01:08:43 +08:00
//===----------------------------------------------------------------------===
// strcmp()
//===----------------------------------------------------------------------===
# define strcmp BUILTIN(strcmp)
2011-06-16 15:13:34 +08:00
int strcmp ( const char * s1 , const char * s2 ) ;
2011-04-13 01:08:43 +08:00
2016-05-20 07:03:49 +08:00
void strcmp_check_modelling ( ) {
char * x = " aa " ;
char * y = " a " ;
clang_analyzer_eval ( strcmp ( x , y ) > 0 ) ; // expected-warning{{TRUE}}
clang_analyzer_eval ( strcmp ( x , y ) < = 0 ) ; // expected-warning{{FALSE}}
clang_analyzer_eval ( strcmp ( x , y ) > 1 ) ; // expected-warning{{UNKNOWN}}
clang_analyzer_eval ( strcmp ( y , x ) < 0 ) ; // expected-warning{{TRUE}}
clang_analyzer_eval ( strcmp ( y , x ) > = 0 ) ; // expected-warning{{FALSE}}
clang_analyzer_eval ( strcmp ( y , x ) < - 1 ) ; // expected-warning{{UNKNOWN}}
}
2011-04-13 01:08:43 +08:00
void strcmp_constant0 ( ) {
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strcmp ( " 123 " , " 123 " ) = = 0 ) ; // expected-warning{{TRUE}}
2011-04-13 01:08:43 +08:00
}
void strcmp_constant_and_var_0 ( ) {
char * x = " 123 " ;
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strcmp ( x , " 123 " ) = = 0 ) ; // expected-warning{{TRUE}}
2011-04-13 01:08:43 +08:00
}
void strcmp_constant_and_var_1 ( ) {
char * x = " 123 " ;
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strcmp ( " 123 " , x ) = = 0 ) ; // expected-warning{{TRUE}}
2011-04-13 01:08:43 +08:00
}
void strcmp_0 ( ) {
char * x = " 123 " ;
char * y = " 123 " ;
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strcmp ( x , y ) = = 0 ) ; // expected-warning{{TRUE}}
2011-04-13 01:08:43 +08:00
}
void strcmp_1 ( ) {
char * x = " 234 " ;
char * y = " 123 " ;
2016-05-20 07:03:49 +08:00
clang_analyzer_eval ( strcmp ( x , y ) > 0 ) ; // expected-warning{{TRUE}}
2011-04-13 01:08:43 +08:00
}
void strcmp_2 ( ) {
char * x = " 123 " ;
char * y = " 234 " ;
2016-05-20 07:03:49 +08:00
clang_analyzer_eval ( strcmp ( x , y ) < 0 ) ; // expected-warning{{TRUE}}
2011-04-13 01:08:43 +08:00
}
void strcmp_null_0 ( ) {
char * x = NULL ;
char * y = " 123 " ;
2019-12-11 08:48:17 +08:00
strcmp ( x , y ) ; // expected-warning{{Null pointer passed as 1st argument to string comparison function}}
2011-04-13 01:08:43 +08:00
}
void strcmp_null_1 ( ) {
char * x = " 123 " ;
char * y = NULL ;
2019-12-11 08:48:17 +08:00
strcmp ( x , y ) ; // expected-warning{{Null pointer passed as 2nd argument to string comparison function}}
2011-04-13 01:08:43 +08:00
}
void strcmp_diff_length_0 ( ) {
char * x = " 12345 " ;
char * y = " 234 " ;
2016-05-20 07:03:49 +08:00
clang_analyzer_eval ( strcmp ( x , y ) < 0 ) ; // expected-warning{{TRUE}}
2011-04-13 01:08:43 +08:00
}
void strcmp_diff_length_1 ( ) {
char * x = " 123 " ;
char * y = " 23456 " ;
2016-05-20 07:03:49 +08:00
clang_analyzer_eval ( strcmp ( x , y ) < 0 ) ; // expected-warning{{TRUE}}
2011-04-13 01:08:43 +08:00
}
void strcmp_diff_length_2 ( ) {
char * x = " 12345 " ;
char * y = " 123 " ;
2016-05-20 07:03:49 +08:00
clang_analyzer_eval ( strcmp ( x , y ) > 0 ) ; // expected-warning{{TRUE}}
2011-04-13 01:08:43 +08:00
}
void strcmp_diff_length_3 ( ) {
char * x = " 123 " ;
char * y = " 12345 " ;
2016-05-20 07:03:49 +08:00
clang_analyzer_eval ( strcmp ( x , y ) < 0 ) ; // expected-warning{{TRUE}}
2011-04-13 01:08:43 +08:00
}
2011-06-16 15:13:34 +08:00
void strcmp_embedded_null ( ) {
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strcmp ( " \0 z " , " \0 y " ) = = 0 ) ; // expected-warning{{TRUE}}
2011-06-16 15:13:34 +08:00
}
void strcmp_unknown_arg ( char * unknown ) {
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strcmp ( unknown , unknown ) = = 0 ) ; // expected-warning{{TRUE}}
2011-06-16 15:13:34 +08:00
}
2016-02-08 08:28:24 +08:00
union argument {
char * f ;
} ;
void function_pointer_cast_helper ( char * * a ) {
strcmp ( " Hi " , * a ) ; // PR24951 crash
}
void strcmp_union_function_pointer_cast ( union argument a ) {
void ( * fPtr ) ( union argument * ) = ( void ( * ) ( union argument * ) ) function_pointer_cast_helper ;
fPtr ( & a ) ;
}
2019-12-11 10:23:39 +08:00
int strcmp_null_argument ( char * a ) {
char * b = 0 ;
// Do not warn about the first argument!
return strcmp ( a , b ) ; // expected-warning{{Null pointer passed as 2nd argument to string comparison function}}
}
2011-04-26 06:21:00 +08:00
//===----------------------------------------------------------------------===
// strncmp()
//===----------------------------------------------------------------------===
# define strncmp BUILTIN(strncmp)
2011-06-16 15:13:34 +08:00
int strncmp ( const char * s1 , const char * s2 , size_t n ) ;
2011-04-26 06:21:00 +08:00
2016-05-20 07:03:49 +08:00
void strncmp_check_modelling ( ) {
char * x = " aa " ;
char * y = " a " ;
clang_analyzer_eval ( strncmp ( x , y , 2 ) > 0 ) ; // expected-warning{{TRUE}}
clang_analyzer_eval ( strncmp ( x , y , 2 ) < = 0 ) ; // expected-warning{{FALSE}}
clang_analyzer_eval ( strncmp ( x , y , 2 ) > 1 ) ; // expected-warning{{UNKNOWN}}
clang_analyzer_eval ( strncmp ( y , x , 2 ) < 0 ) ; // expected-warning{{TRUE}}
clang_analyzer_eval ( strncmp ( y , x , 2 ) > = 0 ) ; // expected-warning{{FALSE}}
clang_analyzer_eval ( strncmp ( y , x , 2 ) < - 1 ) ; // expected-warning{{UNKNOWN}}
}
2011-04-26 06:21:00 +08:00
void strncmp_constant0 ( ) {
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strncmp ( " 123 " , " 123 " , 3 ) = = 0 ) ; // expected-warning{{TRUE}}
2011-04-26 06:21:00 +08:00
}
void strncmp_constant_and_var_0 ( ) {
char * x = " 123 " ;
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strncmp ( x , " 123 " , 3 ) = = 0 ) ; // expected-warning{{TRUE}}
2011-04-26 06:21:00 +08:00
}
void strncmp_constant_and_var_1 ( ) {
char * x = " 123 " ;
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strncmp ( " 123 " , x , 3 ) = = 0 ) ; // expected-warning{{TRUE}}
2011-04-26 06:21:00 +08:00
}
void strncmp_0 ( ) {
char * x = " 123 " ;
char * y = " 123 " ;
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strncmp ( x , y , 3 ) = = 0 ) ; // expected-warning{{TRUE}}
2011-04-26 06:21:00 +08:00
}
void strncmp_1 ( ) {
char * x = " 234 " ;
char * y = " 123 " ;
2016-05-20 07:03:49 +08:00
clang_analyzer_eval ( strncmp ( x , y , 3 ) > 0 ) ; // expected-warning{{TRUE}}
2011-04-26 06:21:00 +08:00
}
void strncmp_2 ( ) {
char * x = " 123 " ;
char * y = " 234 " ;
2016-05-20 07:03:49 +08:00
clang_analyzer_eval ( strncmp ( x , y , 3 ) < 0 ) ; // expected-warning{{TRUE}}
2011-04-26 06:21:00 +08:00
}
void strncmp_null_0 ( ) {
char * x = NULL ;
char * y = " 123 " ;
2019-12-11 08:48:17 +08:00
strncmp ( x , y , 3 ) ; // expected-warning{{Null pointer passed as 1st argument to string comparison function}}
2011-04-26 06:21:00 +08:00
}
void strncmp_null_1 ( ) {
char * x = " 123 " ;
char * y = NULL ;
2019-12-11 08:48:17 +08:00
strncmp ( x , y , 3 ) ; // expected-warning{{Null pointer passed as 2nd argument to string comparison function}}
2011-04-26 06:21:00 +08:00
}
void strncmp_diff_length_0 ( ) {
char * x = " 12345 " ;
char * y = " 234 " ;
2016-05-20 07:03:49 +08:00
clang_analyzer_eval ( strncmp ( x , y , 5 ) < 0 ) ; // expected-warning{{TRUE}}
2011-04-26 06:21:00 +08:00
}
void strncmp_diff_length_1 ( ) {
char * x = " 123 " ;
char * y = " 23456 " ;
2016-05-20 07:03:49 +08:00
clang_analyzer_eval ( strncmp ( x , y , 5 ) < 0 ) ; // expected-warning{{TRUE}}
2011-04-26 06:21:00 +08:00
}
void strncmp_diff_length_2 ( ) {
char * x = " 12345 " ;
char * y = " 123 " ;
2016-05-20 07:03:49 +08:00
clang_analyzer_eval ( strncmp ( x , y , 5 ) > 0 ) ; // expected-warning{{TRUE}}
2011-04-26 06:21:00 +08:00
}
void strncmp_diff_length_3 ( ) {
char * x = " 123 " ;
char * y = " 12345 " ;
2016-05-20 07:03:49 +08:00
clang_analyzer_eval ( strncmp ( x , y , 5 ) < 0 ) ; // expected-warning{{TRUE}}
2011-04-26 06:21:00 +08:00
}
void strncmp_diff_length_4 ( ) {
char * x = " 123 " ;
char * y = " 12345 " ;
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strncmp ( x , y , 3 ) = = 0 ) ; // expected-warning{{TRUE}}
2011-04-26 06:21:00 +08:00
}
void strncmp_diff_length_5 ( ) {
char * x = " 012 " ;
char * y = " 12345 " ;
2016-05-20 07:03:49 +08:00
clang_analyzer_eval ( strncmp ( x , y , 3 ) < 0 ) ; // expected-warning{{TRUE}}
2011-04-26 06:21:00 +08:00
}
void strncmp_diff_length_6 ( ) {
char * x = " 234 " ;
char * y = " 12345 " ;
2016-05-20 07:03:49 +08:00
clang_analyzer_eval ( strncmp ( x , y , 3 ) > 0 ) ; // expected-warning{{TRUE}}
2011-04-26 06:21:00 +08:00
}
2011-06-16 15:13:34 +08:00
void strncmp_embedded_null ( ) {
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strncmp ( " ab \0 zz " , " ab \0 yy " , 4 ) = = 0 ) ; // expected-warning{{TRUE}}
2011-06-16 15:13:34 +08:00
}
2019-12-11 10:23:39 +08:00
int strncmp_null_argument ( char * a , size_t n ) {
char * b = 0 ;
// Do not warn about the first argument!
return strncmp ( a , b , n ) ; // expected-warning{{Null pointer passed as 2nd argument to string comparison function}}
}
2011-04-28 23:09:11 +08:00
//===----------------------------------------------------------------------===
// strcasecmp()
//===----------------------------------------------------------------------===
# define strcasecmp BUILTIN(strcasecmp)
2011-06-16 15:13:34 +08:00
int strcasecmp ( const char * s1 , const char * s2 ) ;
2011-04-28 23:09:11 +08:00
2016-05-20 07:03:49 +08:00
void strcasecmp_check_modelling ( ) {
char * x = " aa " ;
char * y = " a " ;
clang_analyzer_eval ( strcasecmp ( x , y ) > 0 ) ; // expected-warning{{TRUE}}
clang_analyzer_eval ( strcasecmp ( x , y ) < = 0 ) ; // expected-warning{{FALSE}}
clang_analyzer_eval ( strcasecmp ( x , y ) > 1 ) ; // expected-warning{{UNKNOWN}}
clang_analyzer_eval ( strcasecmp ( y , x ) < 0 ) ; // expected-warning{{TRUE}}
clang_analyzer_eval ( strcasecmp ( y , x ) > = 0 ) ; // expected-warning{{FALSE}}
clang_analyzer_eval ( strcasecmp ( y , x ) < - 1 ) ; // expected-warning{{UNKNOWN}}
}
2011-04-28 23:09:11 +08:00
void strcasecmp_constant0 ( ) {
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strcasecmp ( " abc " , " Abc " ) = = 0 ) ; // expected-warning{{TRUE}}
2011-04-28 23:09:11 +08:00
}
void strcasecmp_constant_and_var_0 ( ) {
char * x = " abc " ;
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strcasecmp ( x , " Abc " ) = = 0 ) ; // expected-warning{{TRUE}}
2011-04-28 23:09:11 +08:00
}
void strcasecmp_constant_and_var_1 ( ) {
char * x = " abc " ;
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strcasecmp ( " Abc " , x ) = = 0 ) ; // expected-warning{{TRUE}}
2011-04-28 23:09:11 +08:00
}
void strcasecmp_0 ( ) {
char * x = " abc " ;
char * y = " Abc " ;
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strcasecmp ( x , y ) = = 0 ) ; // expected-warning{{TRUE}}
2011-04-28 23:09:11 +08:00
}
void strcasecmp_1 ( ) {
char * x = " Bcd " ;
char * y = " abc " ;
2016-05-20 07:03:49 +08:00
clang_analyzer_eval ( strcasecmp ( x , y ) > 0 ) ; // expected-warning{{TRUE}}
2011-04-28 23:09:11 +08:00
}
void strcasecmp_2 ( ) {
char * x = " abc " ;
char * y = " Bcd " ;
2016-05-20 07:03:49 +08:00
clang_analyzer_eval ( strcasecmp ( x , y ) < 0 ) ; // expected-warning{{TRUE}}
2011-04-28 23:09:11 +08:00
}
void strcasecmp_null_0 ( ) {
char * x = NULL ;
char * y = " 123 " ;
2019-12-11 08:48:17 +08:00
strcasecmp ( x , y ) ; // expected-warning{{Null pointer passed as 1st argument to string comparison function}}
2011-04-28 23:09:11 +08:00
}
void strcasecmp_null_1 ( ) {
char * x = " 123 " ;
char * y = NULL ;
2019-12-11 08:48:17 +08:00
strcasecmp ( x , y ) ; // expected-warning{{Null pointer passed as 2nd argument to string comparison function}}
2011-04-28 23:09:11 +08:00
}
void strcasecmp_diff_length_0 ( ) {
char * x = " abcde " ;
char * y = " aBd " ;
2016-05-20 07:03:49 +08:00
clang_analyzer_eval ( strcasecmp ( x , y ) < 0 ) ; // expected-warning{{TRUE}}
2011-04-28 23:09:11 +08:00
}
void strcasecmp_diff_length_1 ( ) {
char * x = " abc " ;
char * y = " aBdef " ;
2016-05-20 07:03:49 +08:00
clang_analyzer_eval ( strcasecmp ( x , y ) < 0 ) ; // expected-warning{{TRUE}}
2011-04-28 23:09:11 +08:00
}
void strcasecmp_diff_length_2 ( ) {
char * x = " aBcDe " ;
char * y = " abc " ;
2016-05-20 07:03:49 +08:00
clang_analyzer_eval ( strcasecmp ( x , y ) > 0 ) ; // expected-warning{{TRUE}}
2011-04-28 23:09:11 +08:00
}
void strcasecmp_diff_length_3 ( ) {
char * x = " aBc " ;
char * y = " abcde " ;
2016-05-20 07:03:49 +08:00
clang_analyzer_eval ( strcasecmp ( x , y ) < 0 ) ; // expected-warning{{TRUE}}
2011-04-28 23:09:11 +08:00
}
2011-05-03 03:05:49 +08:00
2011-06-16 15:13:34 +08:00
void strcasecmp_embedded_null ( ) {
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strcasecmp ( " ab \0 zz " , " ab \0 yy " ) = = 0 ) ; // expected-warning{{TRUE}}
2011-06-16 15:13:34 +08:00
}
2019-12-11 10:23:39 +08:00
int strcasecmp_null_argument ( char * a ) {
char * b = 0 ;
// Do not warn about the first argument!
return strcasecmp ( a , b ) ; // expected-warning{{Null pointer passed as 2nd argument to string comparison function}}
}
2011-05-03 03:05:49 +08:00
//===----------------------------------------------------------------------===
// strncasecmp()
//===----------------------------------------------------------------------===
# define strncasecmp BUILTIN(strncasecmp)
2011-06-16 15:13:34 +08:00
int strncasecmp ( const char * s1 , const char * s2 , size_t n ) ;
2011-05-03 03:05:49 +08:00
2016-05-20 07:03:49 +08:00
void strncasecmp_check_modelling ( ) {
char * x = " aa " ;
char * y = " a " ;
clang_analyzer_eval ( strncasecmp ( x , y , 2 ) > 0 ) ; // expected-warning{{TRUE}}
clang_analyzer_eval ( strncasecmp ( x , y , 2 ) < = 0 ) ; // expected-warning{{FALSE}}
clang_analyzer_eval ( strncasecmp ( x , y , 2 ) > 1 ) ; // expected-warning{{UNKNOWN}}
clang_analyzer_eval ( strncasecmp ( y , x , 2 ) < 0 ) ; // expected-warning{{TRUE}}
clang_analyzer_eval ( strncasecmp ( y , x , 2 ) > = 0 ) ; // expected-warning{{FALSE}}
clang_analyzer_eval ( strncasecmp ( y , x , 2 ) < - 1 ) ; // expected-warning{{UNKNOWN}}
}
2011-05-03 03:05:49 +08:00
void strncasecmp_constant0 ( ) {
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strncasecmp ( " abc " , " Abc " , 3 ) = = 0 ) ; // expected-warning{{TRUE}}
2011-05-03 03:05:49 +08:00
}
void strncasecmp_constant_and_var_0 ( ) {
char * x = " abc " ;
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strncasecmp ( x , " Abc " , 3 ) = = 0 ) ; // expected-warning{{TRUE}}
2011-05-03 03:05:49 +08:00
}
void strncasecmp_constant_and_var_1 ( ) {
char * x = " abc " ;
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strncasecmp ( " Abc " , x , 3 ) = = 0 ) ; // expected-warning{{TRUE}}
2011-05-03 03:05:49 +08:00
}
void strncasecmp_0 ( ) {
char * x = " abc " ;
char * y = " Abc " ;
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strncasecmp ( x , y , 3 ) = = 0 ) ; // expected-warning{{TRUE}}
2011-05-03 03:05:49 +08:00
}
void strncasecmp_1 ( ) {
char * x = " Bcd " ;
char * y = " abc " ;
2016-05-20 07:03:49 +08:00
clang_analyzer_eval ( strncasecmp ( x , y , 3 ) > 0 ) ; // expected-warning{{TRUE}}
2011-05-03 03:05:49 +08:00
}
void strncasecmp_2 ( ) {
char * x = " abc " ;
char * y = " Bcd " ;
2016-05-20 07:03:49 +08:00
clang_analyzer_eval ( strncasecmp ( x , y , 3 ) < 0 ) ; // expected-warning{{TRUE}}
2011-05-03 03:05:49 +08:00
}
void strncasecmp_null_0 ( ) {
char * x = NULL ;
char * y = " 123 " ;
2019-12-11 08:48:17 +08:00
strncasecmp ( x , y , 3 ) ; // expected-warning{{Null pointer passed as 1st argument to string comparison function}}
2011-05-03 03:05:49 +08:00
}
void strncasecmp_null_1 ( ) {
char * x = " 123 " ;
char * y = NULL ;
2019-12-11 08:48:17 +08:00
strncasecmp ( x , y , 3 ) ; // expected-warning{{Null pointer passed as 2nd argument to string comparison function}}
2011-05-03 03:05:49 +08:00
}
void strncasecmp_diff_length_0 ( ) {
char * x = " abcde " ;
char * y = " aBd " ;
2016-05-20 07:03:49 +08:00
clang_analyzer_eval ( strncasecmp ( x , y , 5 ) < 0 ) ; // expected-warning{{TRUE}}
2011-05-03 03:05:49 +08:00
}
void strncasecmp_diff_length_1 ( ) {
char * x = " abc " ;
char * y = " aBdef " ;
2016-05-20 07:03:49 +08:00
clang_analyzer_eval ( strncasecmp ( x , y , 5 ) < 0 ) ; // expected-warning{{TRUE}}
2011-05-03 03:05:49 +08:00
}
void strncasecmp_diff_length_2 ( ) {
char * x = " aBcDe " ;
char * y = " abc " ;
2016-05-20 07:03:49 +08:00
clang_analyzer_eval ( strncasecmp ( x , y , 5 ) > 0 ) ; // expected-warning{{TRUE}}
2011-05-03 03:05:49 +08:00
}
void strncasecmp_diff_length_3 ( ) {
char * x = " aBc " ;
char * y = " abcde " ;
2016-05-20 07:03:49 +08:00
clang_analyzer_eval ( strncasecmp ( x , y , 5 ) < 0 ) ; // expected-warning{{TRUE}}
2011-05-03 03:05:49 +08:00
}
void strncasecmp_diff_length_4 ( ) {
char * x = " abcde " ;
char * y = " aBc " ;
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strncasecmp ( x , y , 3 ) = = 0 ) ; // expected-warning{{TRUE}}
2011-05-03 03:05:49 +08:00
}
void strncasecmp_diff_length_5 ( ) {
char * x = " abcde " ;
char * y = " aBd " ;
2016-05-20 07:03:49 +08:00
clang_analyzer_eval ( strncasecmp ( x , y , 3 ) < 0 ) ; // expected-warning{{TRUE}}
2011-05-03 03:05:49 +08:00
}
void strncasecmp_diff_length_6 ( ) {
char * x = " aBDe " ;
char * y = " abc " ;
2016-05-20 07:03:49 +08:00
clang_analyzer_eval ( strncasecmp ( x , y , 3 ) > 0 ) ; // expected-warning{{TRUE}}
2011-05-03 03:05:49 +08:00
}
2011-06-16 15:13:34 +08:00
void strncasecmp_embedded_null ( ) {
2012-05-17 00:01:10 +08:00
clang_analyzer_eval ( strncasecmp ( " ab \0 zz " , " ab \0 yy " , 4 ) = = 0 ) ; // expected-warning{{TRUE}}
2011-06-16 15:13:34 +08:00
}
2013-03-16 07:34:29 +08:00
2019-12-11 10:23:39 +08:00
int strncasecmp_null_argument ( char * a , size_t n ) {
char * b = 0 ;
// Do not warn about the first argument!
return strncasecmp ( a , b , n ) ; // expected-warning{{Null pointer passed as 2nd argument to string comparison function}}
}
2013-04-23 07:18:42 +08:00
//===----------------------------------------------------------------------===
// strsep()
//===----------------------------------------------------------------------===
char * strsep ( char * * stringp , const char * delim ) ;
void strsep_null_delim ( char * s ) {
2019-12-11 08:48:17 +08:00
strsep ( & s , NULL ) ; // expected-warning{{Null pointer passed as 2nd argument to strsep()}}
2013-04-23 07:18:42 +08:00
}
void strsep_null_search ( ) {
2019-12-11 08:48:17 +08:00
strsep ( NULL , " " ) ; // expected-warning{{Null pointer passed as 1st argument to strsep()}}
2013-04-23 07:18:42 +08:00
}
void strsep_return_original_pointer ( char * s ) {
char * original = s ;
char * result = strsep ( & s , " " ) ; // no-warning
clang_analyzer_eval ( original = = result ) ; // expected-warning{{TRUE}}
}
void strsep_null_string ( ) {
char * s = NULL ;
char * result = strsep ( & s , " " ) ; // no-warning
clang_analyzer_eval ( result = = NULL ) ; // expected-warning{{TRUE}}
}
void strsep_changes_input_pointer ( char * s ) {
char * original = s ;
strsep ( & s , " " ) ; // no-warning
clang_analyzer_eval ( s = = original ) ; // expected-warning{{UNKNOWN}}
clang_analyzer_eval ( s = = NULL ) ; // expected-warning{{UNKNOWN}}
// Check that the value is symbolic.
if ( s = = NULL ) {
clang_analyzer_eval ( s = = NULL ) ; // expected-warning{{TRUE}}
}
}
void strsep_changes_input_string ( ) {
char str [ ] = " abc " ;
clang_analyzer_eval ( str [ 1 ] = = ' b ' ) ; // expected-warning{{TRUE}}
char * s = str ;
strsep ( & s , " b " ) ; // no-warning
// The real strsep will change the first delimiter it finds into a NUL
// character. For now, we just model the invalidation.
clang_analyzer_eval ( str [ 1 ] = = ' b ' ) ; // expected-warning{{UNKNOWN}}
}
2018-05-16 20:37:53 +08:00
//===----------------------------------------------------------------------===
2018-12-12 02:57:07 +08:00
// memset() / explicit_bzero() / bzero()
2018-05-16 20:37:53 +08:00
//===----------------------------------------------------------------------===
void * memset ( void * dest , int ch , size_t count ) ;
2018-12-12 02:57:07 +08:00
void bzero ( void * dst , size_t count ) ;
void explicit_bzero ( void * dest , size_t count ) ;
2018-05-16 20:37:53 +08:00
void * malloc ( size_t size ) ;
void free ( void * ) ;
void memset1_char_array_null ( ) {
char str [ ] = " abcd " ;
clang_analyzer_eval ( strlen ( str ) = = 4 ) ; // expected-warning{{TRUE}}
memset ( str , ' \0 ' , 2 ) ;
clang_analyzer_eval ( strlen ( str ) = = 0 ) ; // expected-warning{{TRUE}}
}
void memset2_char_array_null ( ) {
char str [ ] = " abcd " ;
clang_analyzer_eval ( strlen ( str ) = = 4 ) ; // expected-warning{{TRUE}}
memset ( str , ' \0 ' , strlen ( str ) + 1 ) ;
clang_analyzer_eval ( strlen ( str ) = = 0 ) ; // expected-warning{{TRUE}}
clang_analyzer_eval ( str [ 2 ] = = 0 ) ; // expected-warning{{TRUE}}
}
void memset3_char_malloc_null ( ) {
char * str = ( char * ) malloc ( 10 * sizeof ( char ) ) ;
memset ( str + 1 , ' \0 ' , 8 ) ;
clang_analyzer_eval ( str [ 1 ] = = 0 ) ; // expected-warning{{UNKNOWN}}
free ( str ) ;
}
void memset4_char_malloc_null ( ) {
char * str = ( char * ) malloc ( 10 * sizeof ( char ) ) ;
//void *str = malloc(10 * sizeof(char));
memset ( str , ' \0 ' , 10 ) ;
clang_analyzer_eval ( str [ 1 ] = = 0 ) ; // expected-warning{{TRUE}}
clang_analyzer_eval ( strlen ( str ) = = 0 ) ; // expected-warning{{TRUE}}
free ( str ) ;
}
# ifdef SUPPRESS_OUT_OF_BOUND
void memset5_char_malloc_overflow_null ( ) {
char * str = ( char * ) malloc ( 10 * sizeof ( char ) ) ;
memset ( str , ' \0 ' , 12 ) ;
clang_analyzer_eval ( str [ 1 ] = = 0 ) ; // expected-warning{{UNKNOWN}}
free ( str ) ;
}
# endif
void memset6_char_array_nonnull ( ) {
char str [ ] = " abcd " ;
clang_analyzer_eval ( strlen ( str ) = = 4 ) ; // expected-warning{{TRUE}}
memset ( str , ' 0 ' , 2 ) ;
clang_analyzer_eval ( str [ 0 ] = = ' a ' ) ; // expected-warning{{UNKNOWN}}
clang_analyzer_eval ( strlen ( str ) = = 4 ) ; // expected-warning{{UNKNOWN}}
}
# ifdef SUPPRESS_OUT_OF_BOUND
void memset8_char_array_nonnull ( ) {
char str [ 5 ] = " abcd " ;
clang_analyzer_eval ( strlen ( str ) = = 4 ) ; // expected-warning{{TRUE}}
2019-03-19 03:23:45 +08:00
memset ( str , ' 0 ' , 10 ) ; // expected-warning{{'memset' will always overflow; destination buffer has size 5, but size argument is 10}}
2018-05-16 20:37:53 +08:00
clang_analyzer_eval ( str [ 0 ] ! = ' 0 ' ) ; // expected-warning{{UNKNOWN}}
clang_analyzer_eval ( strlen ( str ) > = 10 ) ; // expected-warning{{TRUE}}
clang_analyzer_eval ( strlen ( str ) < 10 ) ; // expected-warning{{FALSE}}
}
# endif
struct POD_memset {
int num ;
char c ;
} ;
void memset10_struct ( ) {
struct POD_memset pod ;
char * str = ( char * ) & pod ;
pod . num = 1 ;
pod . c = 1 ;
clang_analyzer_eval ( pod . num = = 0 ) ; // expected-warning{{FALSE}}
memset ( str , 0 , sizeof ( struct POD_memset ) ) ;
clang_analyzer_eval ( pod . num = = 0 ) ; // expected-warning{{TRUE}}
}
# ifdef SUPPRESS_OUT_OF_BOUND
void memset11_struct_field ( ) {
struct POD_memset pod ;
pod . num = 1 ;
pod . c = ' 1 ' ;
memset ( & pod . num , 0 , sizeof ( struct POD_memset ) ) ;
clang_analyzer_eval ( pod . num = = 0 ) ; // expected-warning{{TRUE}}
clang_analyzer_eval ( pod . c = = ' \0 ' ) ; // expected-warning{{TRUE}}
}
void memset12_struct_field ( ) {
struct POD_memset pod ;
pod . num = 1 ;
pod . c = ' 1 ' ;
2019-03-19 03:23:45 +08:00
memset ( & pod . c , 0 , sizeof ( struct POD_memset ) ) ; // expected-warning {{'memset' will always overflow; destination buffer has size 4, but size argument is 8}}
2018-05-16 20:37:53 +08:00
clang_analyzer_eval ( pod . num = = 0 ) ; // expected-warning{{UNKNOWN}}
clang_analyzer_eval ( pod . c = = 0 ) ; // expected-warning{{UNKNOWN}}
}
union U_memset {
int i ;
double d ;
char c ;
} ;
void memset13_union_field ( ) {
union U_memset u ;
u . i = 5 ;
memset ( & u . i , ' \0 ' , sizeof ( union U_memset ) ) ;
// Note: This should be TRUE, analyzer can't handle union perfectly now.
clang_analyzer_eval ( u . d = = 0 ) ; // expected-warning{{UNKNOWN}}
}
# endif
void memset14_region_cast ( ) {
char * str = ( char * ) malloc ( 10 * sizeof ( int ) ) ;
int * array = ( int * ) str ;
memset ( array , 0 , 10 * sizeof ( int ) ) ;
clang_analyzer_eval ( str [ 10 ] = = ' \0 ' ) ; // expected-warning{{TRUE}}
clang_analyzer_eval ( strlen ( ( char * ) array ) = = 0 ) ; // expected-warning{{TRUE}}
clang_analyzer_eval ( strlen ( str ) = = 0 ) ; // expected-warning{{TRUE}}
free ( str ) ;
}
void memset15_region_cast ( ) {
char * str = ( char * ) malloc ( 10 * sizeof ( int ) ) ;
int * array = ( int * ) str ;
memset ( array , 0 , 5 * sizeof ( int ) ) ;
clang_analyzer_eval ( str [ 10 ] = = ' \0 ' ) ; // expected-warning{{UNKNOWN}}
clang_analyzer_eval ( strlen ( ( char * ) array ) = = 0 ) ; // expected-warning{{TRUE}}
clang_analyzer_eval ( strlen ( str ) = = 0 ) ; // expected-warning{{TRUE}}
free ( str ) ;
}
int memset20_scalar ( ) {
int * x = malloc ( sizeof ( int ) ) ;
* x = 10 ;
memset ( x , 0 , sizeof ( int ) ) ;
int num = 1 / * x ; // expected-warning{{Division by zero}}
free ( x ) ;
return num ;
}
int memset21_scalar ( ) {
int * x = malloc ( sizeof ( int ) ) ;
memset ( x , 0 , 1 ) ;
int num = 1 / * x ;
free ( x ) ;
return num ;
}
void memset22_array ( ) {
int array [ ] = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 } ;
clang_analyzer_eval ( array [ 1 ] = = 2 ) ; // expected-warning{{TRUE}}
memset ( array , 0 , sizeof ( array ) ) ;
clang_analyzer_eval ( array [ 1 ] = = 0 ) ; // expected-warning{{TRUE}}
}
void memset23_array_pod_object ( ) {
struct POD_memset array [ 10 ] ;
array [ 1 ] . num = 10 ;
array [ 1 ] . c = ' c ' ;
clang_analyzer_eval ( array [ 1 ] . num = = 10 ) ; // expected-warning{{TRUE}}
memset ( & array [ 1 ] , 0 , sizeof ( struct POD_memset ) ) ;
clang_analyzer_eval ( array [ 1 ] . num = = 0 ) ; // expected-warning{{UNKNOWN}}
}
void memset24_array_pod_object ( ) {
struct POD_memset array [ 10 ] ;
array [ 1 ] . num = 10 ;
array [ 1 ] . c = ' c ' ;
clang_analyzer_eval ( array [ 1 ] . num = = 10 ) ; // expected-warning{{TRUE}}
memset ( array , 0 , sizeof ( array ) ) ;
clang_analyzer_eval ( array [ 1 ] . num = = 0 ) ; // expected-warning{{TRUE}}
}
void memset25_symbol ( char c ) {
char array [ 10 ] = { 1 } ;
if ( c ! = 0 )
return ;
memset ( array , c , 10 ) ;
clang_analyzer_eval ( strlen ( array ) = = 0 ) ; // expected-warning{{TRUE}}
clang_analyzer_eval ( array [ 4 ] = = 0 ) ; // expected-warning{{TRUE}}
}
void memset26_upper_UCHAR_MAX ( ) {
char array [ 10 ] = { 1 } ;
memset ( array , 1024 , 10 ) ;
clang_analyzer_eval ( strlen ( array ) = = 0 ) ; // expected-warning{{TRUE}}
clang_analyzer_eval ( array [ 4 ] = = 0 ) ; // expected-warning{{TRUE}}
}
2018-12-12 02:57:07 +08:00
void bzero1_null ( ) {
char * a = NULL ;
2019-12-11 08:48:17 +08:00
bzero ( a , 10 ) ; // expected-warning{{Null pointer passed as 1st argument to memory clearance function}}
2018-12-12 02:57:07 +08:00
}
void bzero2_char_array_null ( ) {
char str [ ] = " abcd " ;
clang_analyzer_eval ( strlen ( str ) = = 4 ) ; // expected-warning{{TRUE}}
bzero ( str , 2 ) ;
clang_analyzer_eval ( strlen ( str ) = = 0 ) ; // expected-warning{{TRUE}}
}
void bzero3_char_ptr_null ( ) {
char * str = " abcd " ;
clang_analyzer_eval ( strlen ( str ) = = 4 ) ; // expected-warning{{TRUE}}
bzero ( str + 2 , 2 ) ;
clang_analyzer_eval ( strlen ( str ) = = 0 ) ; // expected-warning{{FALSE}}
}
void explicit_bzero1_null ( ) {
char * a = NULL ;
2019-12-11 08:48:17 +08:00
explicit_bzero ( a , 10 ) ; // expected-warning{{Null pointer passed as 1st argument to memory clearance function}}
2018-12-12 02:57:07 +08:00
}
void explicit_bzero2_clear_mypassword ( ) {
char passwd [ 7 ] = " passwd " ;
explicit_bzero ( passwd , sizeof ( passwd ) ) ; // no-warning
clang_analyzer_eval ( strlen ( passwd ) = = 0 ) ; // expected-warning{{TRUE}}
clang_analyzer_eval ( passwd [ 0 ] = = ' \0 ' ) ; // expected-warning{{TRUE}}
}
void explicit_bzero3_out_ofbound ( ) {
char * privkey = ( char * ) malloc ( 7 ) ;
const char newprivkey [ 10 ] = " mysafekey " ;
strcpy ( privkey , " random " ) ;
explicit_bzero ( privkey , sizeof ( newprivkey ) ) ;
# ifndef SUPPRESS_OUT_OF_BOUND
[analyzer] NFCi: Refactor CStringChecker: use strongly typed internal API
Summary:
I wanted to extend the diagnostics of the CStringChecker with taintedness.
This requires the CStringChecker to be refactored to support a more flexible
reporting mechanism.
This patch does only refactorings, such:
- eliminates always false parameters (like WarnAboutSize)
- reduces the number of parameters
- makes strong types differentiating *source* and *destination* buffers
(same with size expressions)
- binds the argument expression and the index, making diagnostics accurate
and easy to emit
- removes a bunch of default parameters to make it more readable
- remove random const char* warning message parameters, making clear where
and what is going to be emitted
Note that:
- CheckBufferAccess now checks *only* one buffer, this removed about 100 LOC
code duplication
- not every function was refactored to use the /new/ strongly typed API, since
the CString related functions are really closely coupled monolithic beasts,
I will refactor them separately
- all tests are preserved and passing; only the message changed at some places.
In my opinion, these messages are holding the same information.
I would also highlight that this refactoring caught a bug in
clang/test/Analysis/string.c:454 where the diagnostic did not reflect reality.
This catch backs my effort on simplifying this monolithic CStringChecker.
Reviewers: NoQ, baloghadamsoftware, Szelethus, rengolin, Charusso
Reviewed By: NoQ
Subscribers: whisperity, xazax.hun, szepet, rnkovacs, a.sidorin,
mikhail.ramalho, donat.nagy, dkrupp, Charusso, martong, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D74806
2020-04-09 22:06:32 +08:00
// expected-warning@-2 {{Memory clearance function overflows the destination buffer}}
2018-12-12 02:57:07 +08:00
# endif
clang_analyzer_eval ( privkey [ 0 ] = = ' \0 ' ) ;
# ifdef SUPPRESS_OUT_OF_BOUND
// expected-warning@-2 {{UNKNOWN}}
# endif
free ( privkey ) ;
}
2013-03-16 07:34:29 +08:00
//===----------------------------------------------------------------------===
// FIXMEs
//===----------------------------------------------------------------------===
2018-04-06 23:14:32 +08:00
// The analyzer_eval call below should evaluate to true. We are being too
// aggressive in marking the (length of) src symbol dead. The length of dst
// depends on src. This could be explicitly specified in the checker or the
2013-03-16 07:34:29 +08:00
// logic for handling MetadataSymbol in SymbolManager needs to change.
void strcat_symbolic_src_length ( char * src ) {
char dst [ 8 ] = " 1234 " ;
strcat ( dst , src ) ;
clang_analyzer_eval ( strlen ( dst ) > = 4 ) ; // expected-warning{{UNKNOWN}}
}
2018-03-31 09:20:08 +08:00
2013-03-16 07:34:29 +08:00
// The analyzer_eval call below should evaluate to true. Most likely the same
// issue as the test above.
void strncpy_exactly_matching_buffer2 ( char * y ) {
if ( strlen ( y ) > = 4 )
return ;
char x [ 4 ] ;
strncpy ( x , y , 4 ) ; // no-warning
// This time, we know that y fits in x anyway.
clang_analyzer_eval ( strlen ( x ) < = 3 ) ; // expected-warning{{UNKNOWN}}
}
2018-05-16 20:37:53 +08:00
void memset7_char_array_nonnull ( ) {
char str [ 5 ] = " abcd " ;
clang_analyzer_eval ( strlen ( str ) = = 4 ) ; // expected-warning{{TRUE}}
memset ( str , ' 0 ' , 5 ) ;
// FIXME: This should be TRUE.
clang_analyzer_eval ( str [ 0 ] = = ' 0 ' ) ; // expected-warning{{UNKNOWN}}
clang_analyzer_eval ( strlen ( str ) > = 5 ) ; // expected-warning{{TRUE}}
}
void memset16_region_cast ( ) {
char * str = ( char * ) malloc ( 10 * sizeof ( int ) ) ;
int * array = ( int * ) str ;
memset ( array , ' 0 ' , 10 * sizeof ( int ) ) ;
// FIXME: This should be TRUE.
clang_analyzer_eval ( str [ 10 ] = = ' 0 ' ) ; // expected-warning{{UNKNOWN}}
clang_analyzer_eval ( strlen ( ( char * ) array ) > = 10 * sizeof ( int ) ) ; // expected-warning{{TRUE}}
clang_analyzer_eval ( strlen ( str ) > = 10 * sizeof ( int ) ) ; // expected-warning{{TRUE}}
free ( str ) ;
}
# ifdef SUPPRESS_OUT_OF_BOUND
void memset17_region_cast ( ) {
char * str = ( char * ) malloc ( 10 * sizeof ( int ) ) ;
int * array = ( int * ) str ;
memset ( array , ' 0 ' , 12 * sizeof ( int ) ) ;
clang_analyzer_eval ( str [ 10 ] = = ' 0 ' ) ; // expected-warning{{UNKNOWN}}
clang_analyzer_eval ( strlen ( ( char * ) array ) > = 12 * sizeof ( int ) ) ; // expected-warning{{TRUE}}
clang_analyzer_eval ( strlen ( str ) > = 12 * sizeof ( int ) ) ; // expected-warning{{TRUE}}
free ( str ) ;
}
void memset18_memset_multiple_times ( ) {
char * str = ( char * ) malloc ( 10 * sizeof ( char ) ) ;
clang_analyzer_eval ( strlen ( str ) = = 0 ) ; // expected-warning{{UNKNOWN}}
memset ( str + 2 , ' \0 ' , 10 * sizeof ( char ) ) ;
clang_analyzer_eval ( strlen ( str ) = = 0 ) ; // expected-warning{{UNKNOWN}}
clang_analyzer_eval ( str [ 1 ] = = ' \0 ' ) ; // expected-warning{{UNKNOWN}}
memset ( str , ' 0 ' , 10 * sizeof ( char ) ) ;
clang_analyzer_eval ( strlen ( str ) > = 10 ) ; // expected-warning{{TRUE}}
// FIXME: This should be TRUE.
clang_analyzer_eval ( str [ 1 ] = = ' 0 ' ) ; // expected-warning{{UNKNOWN}}
free ( str ) ;
}
void memset19_memset_multiple_times ( ) {
char * str = ( char * ) malloc ( 10 * sizeof ( char ) ) ;
clang_analyzer_eval ( strlen ( str ) = = 0 ) ; // expected-warning{{UNKNOWN}}
memset ( str , ' 0 ' , 10 * sizeof ( char ) ) ;
clang_analyzer_eval ( strlen ( str ) > = 10 ) ; // expected-warning{{TRUE}}
// FIXME: This should be TRUE.
clang_analyzer_eval ( str [ 1 ] = = ' 0 ' ) ; // expected-warning{{UNKNOWN}}
memset ( str + 2 , ' \0 ' , 10 * sizeof ( char ) ) ;
clang_analyzer_eval ( strlen ( str ) > = 10 ) ; // expected-warning{{UNKNOWN}}
clang_analyzer_eval ( str [ 1 ] = = ' 0 ' ) ; // expected-warning{{UNKNOWN}}
free ( str ) ;
}
# endif
// The analyzer does not support binding a symbol with default binding.
void memset27_symbol ( char c ) {
char array [ 10 ] = { 0 } ;
if ( c < 10 )
return ;
memset ( array , c , 10 ) ;
clang_analyzer_eval ( strlen ( array ) > = 10 ) ; // expected-warning{{TRUE}}
// FIXME: This should be TRUE.
clang_analyzer_eval ( array [ 4 ] > = 10 ) ; // expected-warning{{UNKNOWN}}
}
void memset28 ( ) {
short x ;
memset ( & x , 1 , sizeof ( short ) ) ;
// This should be true.
clang_analyzer_eval ( x = = 0x101 ) ; // expected-warning{{UNKNOWN}}
}
[analyzer] Make default bindings to variables actually work.
Default RegionStore bindings represent values that can be obtained by loading
from anywhere within the region, not just the specific offset within the region
that they are said to be bound to. For example, default-binding a character \0
to an int (eg., via memset()) means that the whole int is 0, not just
that its lower byte is 0.
Even though memset and bzero were modeled this way, it didn't work correctly
when applied to simple variables. Eg., in
int x;
memset(x, 0, sizeof(x));
we did produce a default binding, but were unable to read it later, and 'x'
was perceived as an uninitialized variable even after memset.
At the same time, if we replace 'x' with a variable of a structure or array
type, accessing fields or elements of such variable was working correctly,
which was enough for most cases. So this was only a problem for variables of
simple integer/enumeration/floating-point/pointer types.
Fix loading default bindings from RegionStore for regions of simple variables.
Add a unit test to document the API contract as well.
Differential Revision: https://reviews.llvm.org/D60742
llvm-svn: 358722
2019-04-19 07:35:56 +08:00
void memset29_plain_int_zero ( ) {
short x ;
memset ( & x , 0 , sizeof ( short ) ) ;
clang_analyzer_eval ( x = = 0 ) ; // expected-warning{{TRUE}}
}
2019-07-02 07:02:10 +08:00
void test_memset_chk ( ) {
int x ;
__builtin___memset_chk ( & x , 0 , sizeof ( x ) , __builtin_object_size ( & x , 0 ) ) ;
clang_analyzer_eval ( x = = 0 ) ; // expected-warning{{TRUE}}
}