243 lines
4.2 KiB
C
243 lines
4.2 KiB
C
// 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
|
|
}
|