blob: d290cf25f42f765c22ac6473d676cd71621b690a [file] [log] [blame]
// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-config suppress-inlined-defensive-checks=true -verify %s
// Perform inline defensive checks.
void idc(void *p) {
if (p)
;
}
int test01(int *p) {
if (p)
;
return *p; // expected-warning {{Dereference of null pointer}}
}
int test02(int *p, int *x) {
if (p)
;
idc(p);
if (x)
;
return *p; // expected-warning {{Dereference of null pointer}}
}
int test03(int *p, int *x) {
idc(p);
if (p)
;
return *p; // False negative
}
int deref04(int *p) {
return *p; // expected-warning {{Dereference of null pointer}}
}
int test04(int *p) {
if (p)
;
idc(p);
return deref04(p);
}
int test11(int *q, int *x) {
int *p = q;
if (q)
;
if (x)
;
return *p; // expected-warning{{Dereference of null pointer}}
}
int test12(int *q) {
int *p = q;
idc(q);
return *p;
}
int test13(int *q) {
int *p = q;
idc(p);
return *p;
}
int test21(int *q, int *x) {
if (q)
;
if (x)
;
int *p = q;
return *p; // expected-warning{{Dereference of null pointer}}
}
int test22(int *q, int *x) {
idc(q);
if (x)
;
int *p = q;
return *p;
}
int test23(int *q, int *x) {
idc(q);
if (x)
;
int *p = q;
if (!p)
;
return *p; // False negative
}
void use(char *p) {
if (!p)
return;
p[0] = 'a';
}
void test24(char *buffer) {
use(buffer);
buffer[1] = 'b';
}
// Ensure idc works on pointers with constant offset.
void idcchar(const char *s2) {
if(s2)
;
}
void testConstantOffset(char *value) {
char *cursor = value + 5;
idcchar(cursor);
if (*cursor) {
cursor++;
}
}
// Ensure idc works for integer zero values (ex: suppressed div by zero).
void idcZero(int assume) {
if (assume)
;
}
int idcTriggerZeroValue(int m) {
idcZero(m);
return 5/m; // no-warning
}
int idcTriggerZeroValueThroughCall(int i) {
return 5/i; // no-warning
}
void idcTrackZeroValueThroughCall(int x) {
idcZero(x);
idcTriggerZeroValueThroughCall(x);
}
int idcTriggerZeroThroughDoubleAssignemnt(int i) {
return 5/i; // no-warning
}
void idcTrackZeroThroughDoubleAssignemnt(int x) {
idcZero(x);
int y = x;
int z = y;
idcTriggerZeroValueThroughCall(z);
}
struct S {
int f1;
int f2;
};
void idcTrackZeroValueThroughUnaryPointerOperators(struct S *s) {
idc(s);
*(&(s->f1)) = 7; // no-warning
}
void idcTrackZeroValueThroughUnaryPointerOperatorsWithOffset1(struct S *s) {
idc(s);
int *x = &(s->f2);
*x = 7; // no-warning
}
void idcTrackZeroValueThroughUnaryPointerOperatorsWithOffset2(struct S *s) {
idc(s);
int *x = &(s->f2) - 1;
*x = 7; // no-warning
}
void idcTrackZeroValueThroughUnaryPointerOperatorsWithAssignment(struct S *s) {
idc(s);
int *x = &(s->f1);
*x = 7; // no-warning
}
void idcTrackZeroValueThroughManyUnaryPointerOperatorsWithAssignment(struct S *s) {
idc(s);
int *x = &*&(s->f1);
*x = 7; // no-warning
}
void idcTrackZeroValueThroughManyUnaryPointerOperatorsWithAssignmentAndUnaryIncrement(struct S *s) {
idc(s);
int *x = &*&((++s)->f1);
*x = 7; // no-warning
}
struct S2 {
int a[1];
};
void idcTrackZeroValueThroughUnaryPointerOperatorsWithArrayField(struct S2 *s) {
idc(s);
*(&(s->a[0])) = 7; // no-warning
}
void idcTrackConstraintThroughSymbolicRegion(int **x) {
idc(*x);
// FIXME: Should not warn.
**x = 7; // expected-warning{{Dereference of null pointer}}
}
void idcTrackConstraintThroughSymbolicRegionAndParens(int **x) {
idc(*x);
// FIXME: Should not warn.
*(*x) = 7; // expected-warning{{Dereference of null pointer}}
}
int *idcPlainNull(int coin) {
if (coin)
return 0;
static int X;
return &X;
}
void idcTrackZeroValueThroughSymbolicRegion(int coin, int **x) {
*x = idcPlainNull(coin);
**x = 7; // no-warning
}
void idcTrackZeroValueThroughSymbolicRegionAndParens(int coin, int **x) {
*x = idcPlainNull(coin);
*(*x) = 7; // no-warning
}
struct WithInt {
int i;
};
struct WithArray {
struct WithInt arr[1];
};
struct WithArray *idcPlainNullWithArray(int coin) {
if (coin)
return 0;
static struct WithArray S;
return &S;
}
void idcTrackZeroValueThroughSymbolicRegionWithArray(int coin, struct WithArray **s) {
*s = idcPlainNullWithArray(coin);
(*s)->arr[0].i = 1; // no-warning
// Same thing.
(*s)->arr->i = 1; // no-warning
}