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
memset_malloc_2(void)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
memset_malloc_3(void)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
memset_malloc_2_same_size(int i)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
memset_malloc_2_off(void)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 memset (p5_7, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5 " }
204 }
205
206 int i3 = SR (3, INT_MAX);
207
208 {
209 char a5[5];
210 // { dg-message "at offset \\\[3, 5] into destination object 'a5'" "note" { target *-*-* } .-1 }
211 // { dg-message "at offset \\\[2, 5] into destination object 'a5'" "note" { target *-*-* } .-2 }
212 // { dg-message "at offset \\\[1, 5] into destination object 'a5'" "note" { target *-*-* } .-3 }
213 // { dg-message ": destination object 'a5'" "note" { target *-*-* } .-4 }
214 char a9[9];
215 // { dg-message "at offset \\\[4, 9] into destination object 'a9'" "note" { target *-*-* } .-1 }
216 // { dg-message "at offset \\\[3, 9] into destination object 'a9'" "note" { target *-*-* } .-2 }
217 // { dg-message "at offset \\\[2, 9] into destination object 'a9'" "note" { target *-*-* } .-3 }
218 // { dg-message ": destination object 'a9'" "note" { target *-*-* } .-4 }
219 char *p5_p2 = a5 + i2; // 3 bytes left
220 char *p9_p3 = a9 + i3; // 6 bytes left
221 char *p =
222 cond1 ? p5_p2 : p9_p3; // [3 - 6] bytes left
223 char *q = p + i1; // [2 - 5] bytes left
224
225 memset (q, 0, 1);
226 memset (q, 0, 2);
227 memset (q, 0, 3);
228 memset (q, 0, 4);
229 memset (q, 0, 5);
230 memset (q, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5" }
231
232 --q; // [3 - 6] bytes left
233 memset (q, 0, 1);
234 memset (q, 0, 2);
235 memset (q, 0, 3);
236 memset (q, 0, 4);
237 memset (q, 0, 5);
238 memset (q, 0, 6);
239 memset (q, 0, 7); // { dg-warning "memset' writing 7 bytes into a region of size 6" }
240
241 --q; // [4 - 7] bytes left
242 memset (q, 0, 1);
243 memset (q, 0, 2);
244 memset (q, 0, 3);
245 memset (q, 0, 4);
246 memset (q, 0, 5);
247 memset (q, 0, 6);
248 memset (q, 0, 7);
249 memset (q, 0, 8); // { dg-warning "memset' writing 8 bytes into a region of size 7" }
250
251 int m1_x = SR (-1, INT_MAX);
252 int m2_x = SR (-2, INT_MAX);
253
254 q += cond2 ? m1_x : m2_x; // [5 - 9] bytes left
255
256 memset (q, 0, 1);
257 memset (q, 0, 2);
258 memset (q, 0, 3);
259 memset (q, 0, 4);
260 memset (q, 0, 5);
261 memset (q, 0, 6);
262 memset (q, 0, 7);
263 memset (q, 0, 8);
264 memset (q, 0, 9);
265 memset (q, 0, 10); // { dg-warning "memset' writing 10 bytes into a region of size 9" }
266 }
267 }
268