2017-04-16 16:02:28 +00:00
// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core.CastToStruct -analyzer-store=region -verify %s
2009-06-02 17:58:47 +00:00
struct s {
int data ;
int data_array [ 10 ] ;
} ;
typedef struct {
int data ;
} STYPE ;
void g ( char * p ) ;
void g1 ( struct s * p ) ;
// Array to pointer conversion. Array in the struct field.
void f ( void ) {
int a [ 10 ] ;
int ( * p ) [ 10 ] ;
p = & a ;
( * p ) [ 3 ] = 1 ;
struct s d ;
struct s * q ;
q = & d ;
q - > data = 3 ;
d . data_array [ 9 ] = 17 ;
}
// StringLiteral in lvalue context and pointer to array type.
// p: ElementRegion, q: StringRegion
void f2 ( ) {
char * p = " /usr/local " ;
char ( * q ) [ 4 ] ;
q = & " abc " ;
}
// Typedef'ed struct definition.
void f3 ( ) {
STYPE s ;
}
// Initialize array with InitExprList.
void f4 ( ) {
int a [ ] = { 1 , 2 , 3 } ;
int b [ 3 ] = { 1 , 2 } ;
struct s c [ ] = { { 1 , { 1 } } } ;
}
// Struct variable in lvalue context.
// Assign UnknownVal to the whole struct.
void f5 ( ) {
struct s data ;
g1 ( & data ) ;
}
// AllocaRegion test.
void f6 ( ) {
char * p ;
p = __builtin_alloca ( 10 ) ;
g ( p ) ;
char c = * p ;
p [ 1 ] = ' a ' ;
// Test if RegionStore::EvalBinOp converts the alloca region to element
// region.
p + = 2 ;
}
struct s2 ;
void g2 ( struct s2 * p ) ;
// Incomplete struct pointer used as function argument.
void f7 ( ) {
struct s2 * p = __builtin_alloca ( 10 ) ;
g2 ( p ) ;
}
// sizeof() is unsigned while -1 is signed in array index.
void f8 ( ) {
int a [ 10 ] ;
a [ sizeof ( a ) / sizeof ( int ) - 1 ] = 1 ; // no-warning
}
// Initialization of struct array elements.
void f9 ( ) {
struct s a [ 10 ] ;
}
// Initializing array with string literal.
void f10 ( ) {
char a1 [ 4 ] = " abc " ;
char a3 [ 6 ] = " abc " ;
}
// Retrieve the default value of element/field region.
void f11 ( ) {
struct s a ;
g1 ( & a ) ;
if ( a . data = = 0 ) // no-warning
a . data = 1 ;
}
// Convert unsigned offset to signed when creating ElementRegion from
// SymbolicRegion.
void f12 ( int * list ) {
unsigned i = 0 ;
list [ i ] = 1 ;
}
struct s1 {
struct s2 {
int d ;
} e ;
} ;
// The binding of a.e.d should not be removed. Test recursive subregion map
// building: a->e, e->d. Only then 'a' could be added to live region roots.
void f13 ( double timeout ) {
struct s1 a ;
2009-11-18 14:59:57 +00:00
a . e . d = ( int ) timeout ;
2009-06-02 17:58:47 +00:00
if ( a . e . d = = 10 )
a . e . d = 4 ;
}
struct s3 {
int a [ 2 ] ;
} ;
static struct s3 opt ;
// Test if the embedded array is retrieved correctly.
void f14 ( ) {
struct s3 my_opt = opt ;
}
void bar ( int * ) ;
2017-01-02 19:18:08 +00:00
struct s3 gets3 ( ) {
struct s3 s ;
return s ;
}
void accessArrayFieldNoCrash ( ) {
bar ( gets3 ( ) . a ) ;
bar ( ( gets3 ( ) . a ) ) ;
bar ( ( ( gets3 ( ) . a ) ) ) ;
}
2009-06-02 17:58:47 +00:00
// Test if the array is correctly invalidated.
void f15 ( ) {
int a [ 10 ] ;
bar ( a ) ;
if ( a [ 1 ] ) // no-warning
2009-10-14 18:03:49 +00:00
( void ) 1 ;
2009-06-02 17:58:47 +00:00
}
2009-06-14 09:24:02 +00:00
struct s3 p [ 1 ] ;
// Code from postgresql.
// Current cast logic of region store mistakenly leaves the final result region
// an ElementRegion of type 'char'. Then load a nonloc::SymbolVal from it and
// assigns to 'a'.
void f16 ( struct s3 * p ) {
2012-08-19 10:33:04 +00:00
struct s3 a = * ( ( struct s3 * ) ( ( char * ) & p [ 0 ] ) ) ; // expected-warning{{Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption}}
2009-06-14 09:24:02 +00:00
}
2009-07-04 13:58:54 +00:00
void inv ( struct s1 * ) ;
// Invalidate the struct field.
void f17 ( ) {
struct s1 t ;
int x ;
inv ( & t ) ;
if ( t . e . d )
x = 1 ;
}
void read ( char * ) ;
void f18 ( ) {
char * q ;
char * p = ( char * ) __builtin_alloca ( 10 ) ;
read ( p ) ;
q = p ;
q + + ;
if ( * q ) { // no-warning
}
}
2012-12-02 13:20:44 +00:00
// [PR13927] offsetof replacement macro flagged as "dereference of a null pointer"
int offset_of_data_array ( void )
{
return ( ( char * ) & ( ( ( struct s * ) 0 ) - > data_array ) ) - ( ( char * ) 0 ) ; // no-warning
}
2015-05-27 18:47:56 +00:00
int testPointerArithmeticOnVoid ( void * bytes ) {
int p = 0 ;
if ( & bytes [ 0 ] = = & bytes [ 1 ] )
return 6 / p ; // no-warning
return 0 ;
}
int testRValueArraySubscriptExpr ( void * bytes ) {
int * p = ( int * ) & bytes [ 0 ] ;
* p = 0 ;
if ( * ( int * ) & bytes [ 0 ] = = 0 )
return 0 ;
return 5 / ( * p ) ; // no-warning
}