| // 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 |
| } |