1 // RUN: %clang_analyze_cc1 -analyzer-checker=security.PointerSub -analyzer-output=text-minimal -verify %s 2 3 typedef int * Ptr; 4 5 void f1(void) { 6 int x, y, z[10]; 7 int d = &y - &x; // expected-warning{{Subtraction of two pointers that do not point into the same array is undefined behavior}} 8 d = z - &y; // expected-warning{{Subtraction of two pointers that do not point into the same array is undefined behavior}} 9 d = &x - &x; // no-warning (subtraction of any two identical pointers is allowed) 10 d = (long *)&x - (long *)&x; 11 d = (&x + 1) - &x; // no-warning ('&x' is like a single-element array) 12 d = &x - (&x + 1); // no-warning 13 d = (&x + 0) - &x; // no-warning 14 d = (z + 10) - z; // no-warning 15 d = (long long)&y - (long long)&x; // no-warning 16 long long l = 1; 17 d = l - (long long)&y; // no-warning 18 Ptr p1 = &x; 19 Ptr p2 = &y; 20 d = p1 - p2; // expected-warning{{Subtraction of two pointers that do not point into the same array is undefined behavior}} 21 } 22 23 void f2(void) { 24 int a[10], b[10], c; // expected-note{{Array at the left-hand side of subtraction}} \ 25 // expected-note2{{Array at the right-hand side of subtraction}} 26 int *p = &a[2]; 27 int *q = &a[8]; 28 int d = q - p; // no-warning (pointers into the same array) 29 30 q = &b[3]; 31 d = q - p; // expected-warning{{Subtraction of two pointers that}} 32 33 d = &a[4] - a; // no-warning 34 d = &a[2] - p; // no-warning 35 d = &c - p; // expected-warning{{Subtraction of two pointers that}} 36 37 d = (int *)((char *)(&a[4]) + sizeof(int)) - &a[4]; // no-warning (pointers into the same array data) 38 d = (int *)((char *)(&a[4]) + 1) - &a[4]; // expected-warning{{Subtraction of two pointers that}} 39 40 long long a1 = (long long)&a[1]; 41 long long b1 = (long long)&b[1]; 42 d = a1 - b1; 43 } 44 45 void f3(void) { 46 int a[3][4]; // expected-note{{Array at the left-hand side of subtraction}} \ 47 // expected-note2{{Array at the right-hand side of subtraction}} 48 int d; 49 50 d = &(a[2]) - &(a[1]); 51 d = a[2] - a[1]; // expected-warning{{Subtraction of two pointers that}} 52 d = a[1] - a[1]; 53 d = &(a[1][2]) - &(a[1][0]); 54 d = &(a[1][2]) - &(a[0][0]); // expected-warning{{Subtraction of two pointers that}} 55 56 d = (int *)((char *)(&a[2][2]) + sizeof(int)) - &a[2][2]; // expected-warning{{Subtraction of two pointers that}} 57 d = (int *)((char *)(&a[2][2]) + 1) - &a[2][2]; // expected-warning{{Subtraction of two pointers that}} 58 d = (int (*)[4])((char *)&a[2] + sizeof(int (*)[4])) - &a[2]; // expected-warning{{Subtraction of two pointers that}} 59 d = (int (*)[4])((char *)&a[2] + 1) - &a[2]; // expected-warning{{Subtraction of two pointers that}} 60 } 61 62 void f4(void) { 63 int n = 4, m = 3; 64 int a[n][m]; 65 int (*p)[m] = a; // p == &a[0] 66 p += 1; // p == &a[1] 67 68 // FIXME: This is a known problem with -Wpointer-arith (https://github.com/llvm/llvm-project/issues/28328) 69 int d = p - a; // d == 1 // expected-warning{{subtraction of pointers to type 'int[m]' of zero size has undefined behavior}} 70 71 // FIXME: This is a known problem with -Wpointer-arith (https://github.com/llvm/llvm-project/issues/28328) 72 d = &(a[2]) - &(a[1]); // expected-warning{{subtraction of pointers to type 'int[m]' of zero size has undefined behavior}} 73 74 d = a[2] - a[1]; // expected-warning{{Subtraction of two pointers that}} 75 } 76 77 struct S { 78 int a; 79 int b; 80 int c[10]; // expected-note2{{Array at the right-hand side of subtraction}} 81 int d[10]; // expected-note2{{Array at the left-hand side of subtraction}} 82 }; 83 84 void f5(void) { 85 struct S s; 86 int y; 87 int d; 88 89 d = &s.b - &s.a; // expected-warning{{Subtraction of two pointers that}} 90 d = &s.c[0] - &s.a; // expected-warning{{Subtraction of two pointers that}} 91 d = &s.b - &y; // expected-warning{{Subtraction of two pointers that}} 92 d = &s.c[3] - &s.c[2]; 93 d = &s.d[3] - &s.c[2]; // expected-warning{{Subtraction of two pointers that}} 94 d = s.d - s.c; // expected-warning{{Subtraction of two pointers that}} 95 96 struct S sa[10]; 97 d = &sa[2] - &sa[1]; 98 d = &sa[2].a - &sa[1].b; // expected-warning{{Subtraction of two pointers that}} 99 } 100 101 void f6(void) { 102 long long l = 2; 103 char *a1 = (char *)&l; 104 int d = a1[3] - l; 105 106 long long la1[3] = {1}; // expected-note{{Array at the right-hand side of subtraction}} 107 long long la2[3] = {1}; // expected-note{{Array at the left-hand side of subtraction}} 108 char *pla1 = (char *)la1; 109 char *pla2 = (char *)la2; 110 d = pla1[1] - pla1[0]; 111 d = (long long *)&pla1[1] - &l; // expected-warning{{Subtraction of two pointers that}} 112 d = &pla2[3] - &pla1[3]; // expected-warning{{Subtraction of two pointers that}} 113 } 114 115 void f7(int *p) { 116 int a[10]; 117 int d = &a[10] - p; // no-warning ('p' is unknown, even if it cannot point into 'a') 118 } 119 120 void f8(int n) { 121 int a[10] = {1}; 122 int d = a[n] - a[0]; // no-warning 123 } 124 125 int f9(const char *p1) { 126 const char *p2 = p1; 127 --p1; 128 ++p2; 129 return p1 - p2; // no-warning 130 } 131 132 int f10(struct S *p1, struct S *p2) { 133 return &p1->c[5] - &p2->c[5]; // no-warning 134 } 135 136 struct S1 { 137 int a; 138 int b; // expected-note{{Object at the right-hand side of subtraction}} 139 }; 140 141 int f11() { 142 struct S1 s; // expected-note{{Object at the left-hand side of subtraction}} 143 return (char *)&s - (char *)&s.b; // expected-warning{{Subtraction of two pointers that}} 144 } 145 146 struct S2 { 147 char *p1; 148 char *p2; 149 }; 150 151 void init_S2(struct S2 *); 152 153 int f12() { 154 struct S2 s; 155 init_S2(&s); 156 return s.p1 - s.p2; // no-warning (pointers are unknown) 157 } 158