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