1 /* PR middle-end/92936 - missing warning on a past-the-end store to a PHI
2 Exercise warnings for writing into one of two or more allocated objects.
3 { dg-do compile }
4 { dg-options "-O2 -Wall -Wno-array-bounds -ftrack-macro-expansion=0" } */
5
6 #include "range.h"
7
8 #define INT_MAX __INT_MAX__
9
10 extern void* malloc (size_t);
11 extern void* memset (void*, int, size_t);
12 #define memset(d, c, n) sink (memset (d, c, n))
13
14 void sink (int, ...);
15 #define sink(...) sink (0, __VA_ARGS__)
16
17 volatile int cond1, cond2, x;
18
19 #define CHOOSE_MALLOC_2(n1, n2) \
20 (cond1 ? malloc (n1) : malloc (n2))
21 #define CHOOSE_MALLOC_3(n1, n2, n3) \
22 (cond1 < 0 ? malloc (n1) : 0 < cond1 ? malloc (n2) : malloc (n3))
23
24
25 void memset_malloc_2 (void)
26 {
27 {
28 char *p0_1 = CHOOSE_MALLOC_2 (0, 1);
29
30 memset (p0_1, 0, 0);
31 /* Writing more than the smallest destination should trigger a "may
32 write" warning if the access is unconditionally reachable from
33 the block where the pointer to either object is assigned. */
34 memset (p0_1, 0, 1);
35 memset (p0_1, 0, 2); // { dg-warning "memset' writing 2 bytes into a region of size 1 " }
36 memset (p0_1, 0, 9); // { dg-warning "memset' writing 9 bytes into a region of size 1 " }
37 }
38
39 {
40 char *p0_x = CHOOSE_MALLOC_2 (0, x);
41
42 memset (p0_x, 0, 0);
43 memset (p0_x, 0, 1);
44 memset (p0_x, 0, 2);
45 memset (p0_x, 0, 12345);
46 }
47
48 {
49 char *px_x = CHOOSE_MALLOC_2 (x, x);
50
51 memset (px_x, 0, 0);
52 memset (px_x, 0, 1);
53 memset (px_x, 0, 2);
54 memset (px_x, 0, 12345);
55 }
56
57 {
58 char *p3_5 = CHOOSE_MALLOC_2 (3, 5);
59
60 memset (p3_5, 0, 1);
61 memset (p3_5, 0, 3);
62 memset (p3_5, 0, 4);
63 memset (p3_5, 0, 5);
64 memset (p3_5, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5 " }
65 }
66
67 {
68 char *p5_3 = CHOOSE_MALLOC_2 (5, 3);
69
70 memset (p5_3, 0, 3);
71 memset (p5_3, 0, 4);
72 memset (p5_3, 0, 5);
73 memset (p5_3, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5 " }
74 }
75
76 {
77 char *px_3 = CHOOSE_MALLOC_2 (x, 3);
78
79 memset (px_3, 0, 1);
80 memset (px_3, 0, 3);
81 memset (px_3, 0, 4);
82 memset (px_3, 0, 1234);
83 }
84
85 {
86 char *p5_x = CHOOSE_MALLOC_2 (5, x);
87
88 memset (p5_x, 0, 1);
89 memset (p5_x, 0, 5);
90 memset (p5_x, 0, 6);
91 memset (p5_x, 0, 1234);
92 }
93
94 }
95
96
97 void memset_malloc_3 (void)
98 {
99 {
100 char *p0_1_2 = CHOOSE_MALLOC_3 (0, 1, 2);
101 memset (p0_1_2, 0, 0);
102 memset (p0_1_2, 0, 1);
103 memset (p0_1_2, 0, 2);
104 memset (p0_1_2, 0, 3); // { dg-warning "memset' writing 3 bytes into a region of size 2 " }
105 memset (p0_1_2, 0, 9); // { dg-warning "memset' writing 9 bytes into a region of size 2 " }
106 }
107
108 {
109 char *p0_2_x = CHOOSE_MALLOC_3 (0, 2, x);
110
111 memset (p0_2_x, 0, 0);
112 memset (p0_2_x, 0, 1);
113 memset (p0_2_x, 0, 3);
114 memset (p0_2_x, 0, 9);
115 }
116
117 {
118 char *p3_4_5 = CHOOSE_MALLOC_3 (3, 4, 5);
119
120 memset (p3_4_5, 0, 3);
121 memset (p3_4_5, 0, 4);
122 memset (p3_4_5, 0, 5);
123 memset (p3_4_5, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5 " }
124 }
125
126 {
127 char *p5_3_4 = CHOOSE_MALLOC_3 (5, 3, 4);
128
129 memset (p5_3_4, 0, 3);
130 memset (p5_3_4, 0, 4);
131 memset (p5_3_4, 0, 5);
132 memset (p5_3_4, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5 " }
133 }
134
135 {
136 char *p9_8_7 = CHOOSE_MALLOC_3 (9, 8, 7);
137
138 memset (p9_8_7, 0, 7);
139 memset (p9_8_7, 0, 8);
140 memset (p9_8_7, 0, 9);
141 memset (p9_8_7, 0, 10); // { dg-warning "memset' writing 10 bytes into a region of size 9 " }
142 }
143 }
144
145
146 /* Verify conditionally writing into one of two objects with the same
147 size. */
148
149 void memset_malloc_2_same_size (int i)
150 {
151 {
152 char a4_1[4], a4_2[4];
153 char *p4 = cond1 ? a4_1 : a4_2;
154
155 memset (p4, 0, 1);
156 memset (p4, 0, 2);
157 memset (p4, 0, 3);
158 memset (p4, 0, 4);
159 memset (p4, 0, 5); // { dg-warning "memset' writing 5 bytes into a region of size 4" }
160 }
161
162 {
163 char a4_1[4]; // { dg-message "destination object 'a4_1" "note" }
164 char a4_2[4]; // { dg-message "destination object 'a4_2" "note" }
165 char *p4 = cond1 ? a4_1 : a4_2;
166 char *p4_i = p4 + i;
167
168 memset (p4_i, 0, 5); // { dg-warning "memset' writing 5 bytes into a region of size 4" }
169 }
170
171 {
172 if (i < 1)
173 i = 1;
174
175 char a4_1[4]; // { dg-message "at offset \\\[1, 4] into destination object 'a4_1" "note" }
176 char a4_2[4]; // { dg-message "at offset \\\[1, 4] into destination object 'a4_2" "note" }
177 char *p4 = cond1 ? a4_1 : a4_2;
178 char *p4_i = p4 + i;
179
180 memset (p4_i, 0, 3);
181 memset (p4_i, 0, 4); // { dg-warning "memset' writing 4 bytes into a region of size 3 " }
182 }
183 }
184
185
186 void memset_malloc_2_off (void)
187 {
188 int i1 = SR (1, INT_MAX);
189 int i2 = SR (2, INT_MAX);
190
191 {
192 char a5[5]; // { dg-warning "at offset [1, 5] into destination object 'a5'
193 char a7[7]; // { dg-warning "at offset [2, 7] into destination object 'a7'
194 char *p5_p1 = a5 + i1;
195 char *p7_p2 = a7 + i2;
196 char *p5_7 = cond1 ? p5_p1 : p7_p2;
197
198 memset (p5_7, 0, 1);
199 memset (p5_7, 0, 2);
200 memset (p5_7, 0, 3);
201 memset (p5_7, 0, 4);
202 memset (p5_7, 0, 5);
203 /* The warning code conservatively "merges" both the sizes and the offsets
204 into A5 and A7 and so only the second store below is diagnosed but not
205 the first. See PR 103215. The logic needs to be tightened up. */
206 memset (p5_7, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5 " "pr??????" { xfail *-*-* } }
207 memset (p5_7, 0, 7); // { dg-warning "memset' writing 7 bytes into a region of size 6 " }
208 }
209
210 int i3 = SR (3, INT_MAX);
211
212 {
213 char a5[5];
214 // { dg-message "at offset \\\[3, 5] into destination object 'a5'" "note" { target *-*-* } .-1 }
215 // { dg-message "at offset \\\[2, 5] into destination object 'a5'" "note" { target *-*-* } .-2 }
216 // { dg-message "at offset \\\[1, 5] into destination object 'a5'" "note" { target *-*-* } .-3 }
217 // { dg-message ": destination object 'a5'" "note" { target *-*-* } .-4 }
218 char a9[9];
219 // { dg-message "at offset \\\[4, 9] into destination object 'a9'" "note" { target *-*-* } .-1 }
220 // { dg-message "at offset \\\[3, 9] into destination object 'a9'" "note" { target *-*-* } .-2 }
221 // { dg-message "at offset \\\[2, 9] into destination object 'a9'" "note" { target *-*-* } .-3 }
222 // { dg-message "at offset \\\[1, 9] into destination object 'a9'" "note" { target *-*-* } .-4 }
223 // { dg-message ": destination object 'a9'" "pr??????" { xfail *-*-* } .-5 }
224 char *p5_p2 = a5 + i2; // 3 bytes left
225 char *p9_p3 = a9 + i3; // 6 bytes left
226 char *p =
227 cond1 ? p5_p2 : p9_p3; // [3 - 6] bytes left
228 char *q = p + i1; // [2 - 5] bytes left
229
230 memset (q, 0, 1);
231 memset (q, 0, 2);
232 memset (q, 0, 3);
233 memset (q, 0, 4);
234 memset (q, 0, 5);
235 memset (q, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5" "pr??????" { xfail *-*-* } }
236 memset (q, 0, 7); // { dg-warning "memset' writing 7 bytes into a region of size 6" }
237
238 --q; // [3 - 6] bytes left
239 memset (q, 0, 1);
240 memset (q, 0, 2);
241 memset (q, 0, 3);
242 memset (q, 0, 4);
243 memset (q, 0, 5);
244 memset (q, 0, 6);
245 memset (q, 0, 7); // { dg-warning "memset' writing 7 bytes into a region of size 6" "pr??????" { xfail *-*-* } }
246 memset (q, 0, 8); // { dg-warning "memset' writing 8 bytes into a region of size 7" }
247
248 --q; // [4 - 7] bytes left
249 memset (q, 0, 1);
250 memset (q, 0, 2);
251 memset (q, 0, 3);
252 memset (q, 0, 4);
253 memset (q, 0, 5);
254 memset (q, 0, 6);
255 memset (q, 0, 7);
256 memset (q, 0, 8); // { dg-warning "memset' writing 8 bytes into a region of size 7" "pr??????" { xfail *-*-* } }
257 memset (q, 0, 9); // { dg-warning "memset' writing 9 bytes into a region of size 8" }
258
259 int m1_x = SR (-1, INT_MAX);
260 int m2_x = SR (-2, INT_MAX);
261
262 q += cond2 ? m1_x : m2_x; // [5 - 9] bytes left
263
264 memset (q, 0, 1);
265 memset (q, 0, 2);
266 memset (q, 0, 3);
267 memset (q, 0, 4);
268 memset (q, 0, 5);
269 memset (q, 0, 6);
270 memset (q, 0, 7);
271 memset (q, 0, 8);
272 memset (q, 0, 9);
273 memset (q, 0, 10); // { dg-warning "memset' writing 10 bytes into a region of size 9" }
274 }
275 }