2017-03-03 07:30:53 +08:00
// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify %s
// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify %s
// RUN: %clang_cc1 -analyze -DVARIANT -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify %s
// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -DVARIANT -analyzer-checker=alpha.security.taint,core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify %s
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 , . . . ) ;
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 ( ) {
2011-06-20 10:06:40 +08:00
return strlen ( 0 ) ; // expected-warning{{Null pointer argument in call 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.
clang_analyzer_eval ( strlen ( global_str ) = = 0 ) ; // expected-warning{{TRUE}}
}
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 ( ) {
2011-06-20 10:06:40 +08:00
return strnlen ( 0 , 3 ) ; // expected-warning{{Null pointer argument in call 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 ) {
2011-06-20 10:06:40 +08:00
strcpy ( NULL , x ) ; // expected-warning{{Null pointer argument in call to string copy function}}
2010-08-16 15:51:42 +08:00
}
void strcpy_null_src ( char * x ) {
2011-06-20 10:06:40 +08:00
strcpy ( x , NULL ) ; // expected-warning{{Null pointer argument in call 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
}
void strcpy_overflow ( char * y ) {
char x [ 4 ] ;
if ( strlen ( y ) = = 4 )
2011-06-20 10:06:40 +08:00
strcpy ( x , y ) ; // expected-warning{{String copy function overflows destination buffer}}
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
}
void stpcpy_overflow ( char * y ) {
char x [ 4 ] ;
if ( strlen ( y ) = = 4 )
2011-06-20 10:06:40 +08:00
stpcpy ( x , y ) ; // expected-warning{{String copy function overflows destination buffer}}
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 ) {
2011-06-20 10:06:40 +08:00
strcat ( NULL , x ) ; // expected-warning{{Null pointer argument in call to string copy function}}
2011-04-09 23:12:58 +08:00
}
void strcat_null_src ( char * x ) {
2011-06-20 10:06:40 +08:00
strcat ( x , NULL ) ; // expected-warning{{Null pointer argument in call to string copy function}}
2011-04-09 23:12:58 +08:00
}
void strcat_fn ( char * x ) {
2011-06-20 10:06:40 +08:00
strcat ( x , ( char * ) & strcat_fn ) ; // expected-warning{{Argument to string copy 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
}
void strcat_overflow_0 ( char * y ) {
char x [ 4 ] = " 12 " ;
if ( strlen ( y ) = = 4 )
2011-06-20 10:06:40 +08:00
strcat ( x , y ) ; // expected-warning{{String copy function overflows destination buffer}}
2011-04-09 23:12:58 +08:00
}
void strcat_overflow_1 ( char * y ) {
char x [ 4 ] = " 12 " ;
if ( strlen ( y ) = = 3 )
2011-06-20 10:06:40 +08:00
strcat ( x , y ) ; // expected-warning{{String copy function overflows destination buffer}}
2011-04-09 23:12:58 +08:00
}
void strcat_overflow_2 ( char * y ) {
char x [ 4 ] = " 12 " ;
if ( strlen ( y ) = = 2 )
2011-06-20 10:06:40 +08:00
strcat ( x , y ) ; // expected-warning{{String copy function overflows destination buffer}}
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 ) {
strncpy ( NULL , x , 5 ) ; // expected-warning{{Null pointer argument in call to string copy function}}
}
void strncpy_null_src ( char * x ) {
strncpy ( x , NULL , 5 ) ; // expected-warning{{Null pointer argument in call to string copy function}}
}
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
}
void strncpy_overflow ( char * y ) {
char x [ 4 ] ;
if ( strlen ( y ) = = 4 )
strncpy ( x , y , 5 ) ; // expected-warning{{Size argument is greater than the length of the destination buffer}}
}
void strncpy_no_overflow ( char * y ) {
char x [ 4 ] ;
if ( strlen ( y ) = = 3 )
strncpy ( x , y , 5 ) ; // expected-warning{{Size argument is greater than the length of the destination buffer}}
}
void strncpy_no_overflow2 ( char * y , int n ) {
if ( n < = 4 )
return ;
char x [ 4 ] ;
if ( strlen ( y ) = = 3 )
strncpy ( x , y , n ) ; // expected-warning{{Size argument is greater than the length of the destination buffer}}
}
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 ) {
2011-06-20 10:06:40 +08:00
strncat ( NULL , x , 4 ) ; // expected-warning{{Null pointer argument in call to string copy function}}
2011-04-09 23:12:58 +08:00
}
void strncat_null_src ( char * x ) {
2011-06-20 10:06:40 +08:00
strncat ( x , NULL , 4 ) ; // expected-warning{{Null pointer argument in call to string copy function}}
2011-04-09 23:12:58 +08:00
}
void strncat_fn ( char * x ) {
2011-06-20 10:06:40 +08:00
strncat ( x , ( char * ) & strncat_fn , 4 ) ; // expected-warning{{Argument to string copy 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
}
void strncat_overflow_0 ( char * y ) {
char x [ 4 ] = " 12 " ;
if ( strlen ( y ) = = 4 )
2011-06-21 05:55:40 +08:00
strncat ( x , y , strlen ( y ) ) ; // expected-warning{{Size argument is greater than the free space in 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 )
2011-06-21 05:55:40 +08:00
strncat ( x , y , strlen ( y ) ) ; // expected-warning{{Size argument is greater than the free space in 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 )
2011-06-21 05:55:40 +08:00
strncat ( x , y , strlen ( y ) ) ; // expected-warning{{Size argument is greater than the free space in 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 )
2011-06-21 05:55:40 +08:00
strncat ( x , y , 2 ) ; // expected-warning{{Size argument is greater than the free space in the destination buffer}}
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
}
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 " ;
strncat ( dst2 , src , 4 ) ; // expected-warning{{Size argument is greater than the free space in the destination buffer}}
}
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 " ;
strncat ( dst2 , & src [ offset ] , 4 ) ; // expected-warning{{Size argument is greater than the free space in the destination buffer}}
}
// 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 " ;
2011-06-20 10:06:40 +08:00
strcmp ( x , y ) ; // expected-warning{{Null pointer argument in call to string comparison function}}
2011-04-13 01:08:43 +08:00
}
void strcmp_null_1 ( ) {
char * x = " 123 " ;
char * y = NULL ;
2011-06-20 10:06:40 +08:00
strcmp ( x , y ) ; // expected-warning{{Null pointer argument in call 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 ) ;
}
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 " ;
2011-06-20 10:06:40 +08:00
strncmp ( x , y , 3 ) ; // expected-warning{{Null pointer argument in call to string comparison function}}
2011-04-26 06:21:00 +08:00
}
void strncmp_null_1 ( ) {
char * x = " 123 " ;
char * y = NULL ;
2011-06-20 10:06:40 +08:00
strncmp ( x , y , 3 ) ; // expected-warning{{Null pointer argument in call 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
}
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 " ;
2011-06-20 10:06:40 +08:00
strcasecmp ( x , y ) ; // expected-warning{{Null pointer argument in call to string comparison function}}
2011-04-28 23:09:11 +08:00
}
void strcasecmp_null_1 ( ) {
char * x = " 123 " ;
char * y = NULL ;
2011-06-20 10:06:40 +08:00
strcasecmp ( x , y ) ; // expected-warning{{Null pointer argument in call 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
}
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 " ;
2011-06-20 10:06:40 +08:00
strncasecmp ( x , y , 3 ) ; // expected-warning{{Null pointer argument in call to string comparison function}}
2011-05-03 03:05:49 +08:00
}
void strncasecmp_null_1 ( ) {
char * x = " 123 " ;
char * y = NULL ;
2011-06-20 10:06:40 +08:00
strncasecmp ( x , y , 3 ) ; // expected-warning{{Null pointer argument in call 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
2013-04-23 07:18:42 +08:00
//===----------------------------------------------------------------------===
// strsep()
//===----------------------------------------------------------------------===
char * strsep ( char * * stringp , const char * delim ) ;
void strsep_null_delim ( char * s ) {
strsep ( & s , NULL ) ; // expected-warning{{Null pointer argument in call to strsep()}}
}
void strsep_null_search ( ) {
strsep ( NULL , " " ) ; // expected-warning{{Null pointer argument in call to strsep()}}
}
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}}
}
2013-03-16 07:34:29 +08:00
//===----------------------------------------------------------------------===
// FIXMEs
//===----------------------------------------------------------------------===
// 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 explicitely specified in the checker or the
// 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}}
}
// 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}}
}