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