1 /* Verify that -Wstringop-overflow detects writing past the end of each
2 individual element of a multidimensional array.
3 { dg-do compile }
4 { dg-options "-O2 -Wall -Wno-array-bounds -Wno-stringop-truncation" } */
5
6 #define CONCAT(x, y) x ## y
7 #define CAT(name, line) CONCAT (name, line)
8 #define UNIQ_NAME(name) CAT (name, __LINE__)
9
10 typedef __SIZE_TYPE__ size_t;
11
12 extern void* malloc (size_t);
13 extern char* strncpy (char*, const char*, size_t);
14
15 extern char a2_2_8[2][2][8];
16
17 void nowarn_a2_2_8 (const char *s)
18 {
19 // The following trigger -Wstringop-truncation.
20 strncpy (a2_2_8[0][0], s, 8);
21 strncpy (a2_2_8[0][1], s, 8);
22 strncpy (a2_2_8[1][0], s, 8);
23 strncpy (a2_2_8[1][1], s, 8);
24 }
25
26 void warn_a2_2_8 (const char *s)
27 {
28 strncpy (a2_2_8[0][0], s, 9); // { dg-warning "writing 9 bytes into a region of size 8 " }
29 strncpy (a2_2_8[0][1], s, 9); // { dg-warning "writing 9 bytes into a region of size 8 " }
30 strncpy (a2_2_8[1][0], s, 9); // { dg-warning "writing 9 bytes into a region of size 8 " }
31 strncpy (a2_2_8[1][1], s, 9); // { dg-warning "writing 9 bytes into a region of size 8 " }
32 }
33
34
35 extern char a2_3_5[2][3][5];
36
37 void nowarn_a2_3_5 (const char *s)
38 {
39 // The following trigger -Wstringop-truncation.
40 strncpy (a2_3_5[0][0], s, 5);
41 strncpy (a2_3_5[0][1], s, 5);
42 strncpy (a2_3_5[0][2], s, 5);
43 strncpy (a2_3_5[1][0], s, 5);
44 strncpy (a2_3_5[1][1], s, 5);
45 strncpy (a2_3_5[1][2], s, 5);
46 }
47
48 void warn_a2_3_5 (const char *s)
49 {
50 strncpy (a2_3_5[0][0], s, 6); // { dg-warning "writing 6 bytes into a region of size 5 " }
51 strncpy (a2_3_5[0][1], s, 7); // { dg-warning "writing 7 bytes into a region of size 5 " }
52 strncpy (a2_3_5[1][0], s, 8); // { dg-warning "writing 8 bytes into a region of size 5 " }
53 strncpy (a2_3_5[1][1], s, 9); // { dg-warning "writing 9 bytes into a region of size 5 " }
54 }
55
56
57 void* nowarn_malloc_3_5 (const char *s, unsigned n)
58 {
59 if (n < 3 || 5 < n)
60 n = 3;
61 char *p = (char*)malloc (n);
62 strncpy (p + 1, s, 4);
63 return p;
64 }
65
66 void* warn_malloc_3_5 (const char *s, unsigned n)
67 {
68 if (n < 3 || 5 < n)
69 n = 3;
70 char *p = (char*)malloc (n); // { dg-message "at offset 1 into destination object of size \\\[3, 5] allocated by 'malloc'" "note" }
71 // The size below should be a range like the one above.
72 strncpy (p + 1, s, 5); // { dg-warning "writing 5 bytes into a region of size 4 " }
73 return p;
74 }
75
76
77 typedef __attribute__ ((alloc_size (1, 2))) void* UsrAlloc (int, int);
78
79 void* nowarn_use_alloc_3_5 (UsrAlloc *usr_alloc, const char *s, unsigned n)
80 {
81 if (n < 3 || 5 < n)
82 n = 3;
83 char *p = (char*)usr_alloc (n, 3);
84 strncpy (p + 1, s, 14);
85 return p;
86 }
87
88 void* warn_usr_alloc_3_5 (UsrAlloc *usr_alloc, const char *s, unsigned n)
89 {
90 if (n < 3 || 5 < n)
91 n = 3;
92 char *p = (char*)usr_alloc (n, 3); // { dg-message "at offset 1 into destination object of size \\\[9, 15] allocated by 'usr_alloc'" "note" }
93 // The size below should be a range like the one above.
94 strncpy (p + 1, s, 15); // { dg-warning "writing 15 bytes into a region of size 14 " }
95 return p;
96 }
97
98 struct S
99 {
100 char a2_3_4[2][3][4];
101 char a3_4_5[3][4][5];
102 };
103
104 extern struct S sa[];
105
106 void nowarn_sa_cstidx_cstsize (const char* const s[])
107 {
108 strncpy (sa[0].a2_3_4[0][0], s[0], 4);
109 strncpy (sa[0].a2_3_4[0][1], s[1], 4);
110 strncpy (sa[0].a2_3_4[0][2], s[2], 4);
111
112 strncpy (sa[0].a2_3_4[1][0], s[3], 4);
113 strncpy (sa[0].a2_3_4[1][1], s[4], 4);
114 strncpy (sa[0].a2_3_4[1][2], s[5], 4);
115
116 strncpy (sa[1].a2_3_4[0][0], s[6], 4);
117 strncpy (sa[1].a2_3_4[0][1], s[7], 4);
118 strncpy (sa[1].a2_3_4[0][2], s[8], 4);
119
120 strncpy (sa[1].a2_3_4[1][0], s[9], 4);
121 strncpy (sa[1].a2_3_4[1][1], s[10], 4);
122 strncpy (sa[1].a2_3_4[1][2], s[11], 4);
123 }
124
125 void warn_sa_cstidx_cstsize (const char* const s[])
126 {
127 strncpy (sa[0].a2_3_4[0][0], s[0], 5); // { dg-warning "writing 5 bytes into a region of size 4 " }
128 strncpy (sa[0].a2_3_4[0][1], s[1], 6); // { dg-warning "writing 6 bytes into a region of size 4 " }
129 strncpy (sa[0].a2_3_4[0][2], s[2], 7); // { dg-warning "writing 7 bytes into a region of size 4 " }
130
131 strncpy (sa[0].a2_3_4[1][0], s[3], 5); // { dg-warning "writing 5 bytes into a region of size 4 " }
132 strncpy (sa[0].a2_3_4[1][1], s[4], 6); // { dg-warning "writing 6 bytes into a region of size 4 " }
133 strncpy (sa[0].a2_3_4[1][2], s[5], 7); // { dg-warning "writing 7 bytes into a region of size 4 " }
134
135 strncpy (sa[1].a2_3_4[0][0], s[6], 5); // { dg-warning "writing 5 bytes into a region of size 4 " }
136 strncpy (sa[1].a2_3_4[0][1], s[7], 6); // { dg-warning "writing 6 bytes into a region of size 4 " }
137 strncpy (sa[1].a2_3_4[0][2], s[8], 7); // { dg-warning "writing 7 bytes into a region of size 4 " }
138
139 strncpy (sa[1].a2_3_4[1][0], s[9], 5); // { dg-warning "writing 5 bytes into a region of size 4 " }
140 strncpy (sa[1].a2_3_4[1][1], s[10], 6); // { dg-warning "writing 6 bytes into a region of size 4 " }
141 strncpy (sa[1].a2_3_4[1][2], s[11], 7); // { dg-warning "writing 7 bytes into a region of size 4 " }
142 }
143
144 void nowarn_sa_cstidx_varsize (const char* const s[], unsigned n)
145 {
146 strncpy (sa[0].a2_3_4[0][0], s[0], n);
147 strncpy (sa[0].a2_3_4[0][1], s[1], n);
148 strncpy (sa[0].a2_3_4[0][2], s[2], n);
149
150 strncpy (sa[0].a2_3_4[1][0], s[3], n);
151 strncpy (sa[0].a2_3_4[1][1], s[4], n);
152 strncpy (sa[0].a2_3_4[1][2], s[5], n);
153
154 strncpy (sa[1].a2_3_4[0][0], s[6], n);
155 strncpy (sa[1].a2_3_4[0][1], s[7], n);
156 strncpy (sa[1].a2_3_4[0][2], s[8], n);
157
158 strncpy (sa[1].a2_3_4[1][0], s[9], n);
159 strncpy (sa[1].a2_3_4[1][1], s[10], n);
160 strncpy (sa[1].a2_3_4[1][2], s[11], n);
161 }
162
163 void nowarn_sa_loop (const char* const s[], unsigned n)
164 {
165 for (unsigned i0 = 0; i0 != 5; ++i0)
166 for (unsigned i1 = 0; i1 != 3; ++i1)
167 for (unsigned i2 = 0; i2 != 2; ++i2)
168 strncpy (sa[i0].a2_3_4[i1][i2], s[i2], n);
169 }
170
171
172 /* Verify that a note after the warning points to the accessed object
173 and mentions the starting offset of the access. Another alternative
174 might be for the offset to be the starting offset of the overflow.
175 As it is, it's not clear to which of the two the offset refers. */
176
177 void test_note (const char *s)
178 {
179 extern void sink (void*);
180
181 {
182 char a[1][1][2]; // { dg-message "destination object" "note" }
183 strncpy (a[0][0], s, 3); // { dg-warning "writing 3 bytes into a region of size 2 " }
184 sink (a);
185 }
186
187 {
188 char a[1][1][2]; // { dg-message "at offset 2 into " "note" }
189 strncpy (a[0][1], s, 3); // { dg-warning "writing 3 bytes into a region of size 0 " }
190 sink (a);
191 }
192
193 {
194 char a[1][2][2]; // { dg-message "destination object" "note" }
195 strncpy (a[0][0], s, 3); // { dg-warning "writing 3 bytes into a region of size 2 " }
196 sink (a);
197 }
198
199 {
200 char a[1][2][2]; // { dg-message "at offset 2 into " "note" }
201 strncpy (a[0][1], s, 3); // { dg-warning "writing 3 bytes into a region of size 2 " }
202 sink (a);
203 }
204
205 {
206 char a[1][2][2]; // { dg-message "at offset 4 into " "note" }
207 strncpy (a[1][0], s, 3); // { dg-warning "writing 3 bytes into a region of size 0 " }
208 sink (a);
209 }
210
211 {
212 char a[2][1][2]; // { dg-message "at offset 2 into " "note" }
213 strncpy (a[0][1], s, 3); // { dg-warning "writing 3 bytes into a region of size 0 " }
214 sink (a);
215 }
216
217 {
218 char a[2][1][2]; // { dg-message "at offset 2 into " "note" }
219 strncpy (a[1][0], s, 3); // { dg-warning "writing 3 bytes into a region of size 2 " }
220 sink (a);
221 }
222
223 {
224 char a[2][2][3]; // { dg-message "at offset 9 into " "note" }
225 strncpy (a[1][1], s, 4); // { dg-warning "writing 4 bytes into a region of size 3 " }
226 sink (a);
227 }
228
229 {
230 char a[2][3][3]; // { dg-message "at offset 12 into " "note" }
231 strncpy (a[1][1], s, 5); // { dg-warning "writing 5 bytes into a region of size 3 " }
232 sink (a);
233 }
234
235 {
236 char a[2][3][3]; // { dg-message "at offset 12 into " "note" }
237 strncpy (a[1][1], s, 6); // { dg-warning "writing 6 bytes into a region of size 3 " }
238 sink (a);
239 }
240
241 {
242 char a[2][3][3]; // { dg-message "at offset 15 into " "note" }
243 strncpy (a[1][2], s, 7); // { dg-warning "writing 7 bytes into a region of size 3 " }
244 sink (a);
245 }
246
247 }