llvm-project/clang/test/Analysis/array-struct.c

213 lines
3.8 KiB
C

// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core.CastToStruct -analyzer-store=region -analyzer-constraints=range -verify %s
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;
a.e.d = (int) timeout;
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*);
struct s3 gets3() {
struct s3 s;
return s;
}
void accessArrayFieldNoCrash() {
bar(gets3().a);
bar((gets3().a));
bar(((gets3().a)));
}
// Test if the array is correctly invalidated.
void f15() {
int a[10];
bar(a);
if (a[1]) // no-warning
(void)1;
}
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) {
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}}
}
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
}
}
// [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
}
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
}