1 /* Copyright (C) 2004, 2005  Free Software Foundation.
2 
3    Ensure builtin __memset_chk performs correctly.  */
4 
5 extern void abort (void);
6 typedef __SIZE_TYPE__ size_t;
7 extern size_t strlen(const char *);
8 extern void *memcpy (void *, const void *, size_t);
9 extern void *memset (void *, int, size_t);
10 extern int memcmp (const void *, const void *, size_t);
11 
12 #include "chk.h"
13 
14 char buffer[32];
15 int argc = 1;
16 volatile size_t l1 = 1;  /* prevent constant propagation to happen when whole program assumptions are made.  */
17 volatile char *s3 = "FGH"; /* prevent constant propagation to happen when whole program assumptions are made.  */
18 char *s4;
19 
20 void
21 __attribute__((noinline))
test1(void)22 test1 (void)
23 {
24   memset_disallowed = 1;
25   chk_calls = 0;
26   memset (buffer, argc, 0);
27   memset (buffer, argc, 1);
28   memset (buffer, argc, 2);
29   memset (buffer, argc, 3);
30   memset (buffer, argc, 4);
31   memset (buffer, argc, 5);
32   memset (buffer, argc, 6);
33   memset (buffer, argc, 7);
34   memset (buffer, argc, 8);
35   memset (buffer, argc, 9);
36   memset (buffer, argc, 10);
37   memset (buffer, argc, 11);
38   memset (buffer, argc, 12);
39   memset (buffer, argc, 13);
40   memset (buffer, argc, 14);
41   memset (buffer, argc, 15);
42   memset (buffer, argc, 16);
43   memset (buffer, argc, 17);
44   memset_disallowed = 0;
45   if (chk_calls)
46     abort ();
47 }
48 
49 /* Test whether compile time checking is done where it should
50    and so is runtime object size checking.  */
51 void
52 __attribute__((noinline))
test2(void)53 test2 (void)
54 {
55   struct A { char buf1[10]; char buf2[10]; } a;
56   char *r = l1 == 1 ? &a.buf1[5] : &a.buf2[4];
57   char buf3[20];
58   int i;
59   size_t l;
60 
61   /* The following calls should do runtime checking
62      - length is not known, but destination is.  */
63   chk_calls = 0;
64   memset (a.buf1 + 2, 'a', l1);
65   memset (r, '\0', l1 + 1);
66   r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
67   memset (r, argc, l1 + 2);
68   memset (r + 2, 'Q', l1);
69   r = buf3;
70   for (i = 0; i < 4; ++i)
71     {
72       if (i == l1 - 1)
73 	r = &a.buf1[1];
74       else if (i == l1)
75 	r = &a.buf2[7];
76       else if (i == l1 + 1)
77 	r = &buf3[5];
78       else if (i == l1 + 2)
79 	r = &a.buf1[9];
80     }
81   memset (r, '\0', l1);
82   if (chk_calls != 5)
83     abort ();
84 
85   /* Following have known destination and known length,
86      so if optimizing certainly shouldn't result in the checking
87      variants.  */
88   chk_calls = 0;
89   memset (a.buf1 + 2, '\0', 1);
90   memset (r, argc, 2);
91   r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
92   memset (r, 'N', 3);
93   r = buf3;
94   l = 4;
95   for (i = 0; i < 4; ++i)
96     {
97       if (i == l1 - 1)
98 	r = &a.buf1[1], l = 2;
99       else if (i == l1)
100 	r = &a.buf2[7], l = 3;
101       else if (i == l1 + 1)
102 	r = &buf3[5], l = 4;
103       else if (i == l1 + 2)
104 	r = &a.buf1[9], l = 1;
105     }
106   memset (r, 'H', 1);
107   /* Here, l is known to be at most 4 and __builtin_object_size (&buf3[16], 0)
108      is 4, so this doesn't need runtime checking.  */
109   memset (&buf3[16], 'd', l);
110   /* Neither length nor destination known.  Doesn't need runtime checking.  */
111   memset (s4, 'a', l1);
112   memset (s4 + 2, '\0', l1 + 2);
113   /* Destination unknown.  */
114   memset (s4 + 4, 'b', 2);
115   memset (s4 + 6, '\0', 4);
116   if (chk_calls)
117     abort ();
118   chk_calls = 0;
119 }
120 
121 /* Test whether runtime and/or compile time checking catches
122    buffer overflows.  */
123 void
124 __attribute__((noinline))
test3(void)125 test3 (void)
126 {
127   struct A { char buf1[10]; char buf2[10]; } a;
128   char buf3[20];
129 
130   chk_fail_allowed = 1;
131   /* Runtime checks.  */
132   if (__builtin_setjmp (chk_fail_buf) == 0)
133     {
134       memset (&a.buf2[9], '\0', l1 + 1);
135       abort ();
136     }
137   if (__builtin_setjmp (chk_fail_buf) == 0)
138     {
139       memset (&a.buf2[7], 'T', strlen (s3) + 1);
140       abort ();
141     }
142   /* This should be detectable at compile time already.  */
143   if (__builtin_setjmp (chk_fail_buf) == 0)
144     {
145       memset (&buf3[19], 'b', 2);
146       abort ();
147     }
148   chk_fail_allowed = 0;
149 }
150 
151 #ifndef MAX_OFFSET
152 #define MAX_OFFSET (sizeof (long long))
153 #endif
154 
155 #ifndef MAX_COPY
156 #define MAX_COPY (10 * sizeof (long long))
157 #define MAX_COPY2 15
158 #else
159 #define MAX_COPY2 MAX_COPY
160 #endif
161 
162 #ifndef MAX_EXTRA
163 #define MAX_EXTRA (sizeof (long long))
164 #endif
165 
166 #define MAX_LENGTH (MAX_OFFSET + MAX_COPY + MAX_EXTRA)
167 #define MAX_LENGTH2 (MAX_OFFSET + MAX_COPY2 + MAX_EXTRA)
168 
169 static union {
170   char buf[MAX_LENGTH];
171   long long align_int;
172   long double align_fp;
173 } u;
174 
175 char A = 'A';
176 
177 void
178 __attribute__((noinline))
test4(void)179 test4 (void)
180 {
181   int off, len, i;
182   char *p, *q;
183 
184   for (off = 0; off < MAX_OFFSET; off++)
185     for (len = 1; len < MAX_COPY; len++)
186       {
187 	for (i = 0; i < MAX_LENGTH; i++)
188 	  u.buf[i] = 'a';
189 
190 	p = memset (u.buf + off, '\0', len);
191 	if (p != u.buf + off)
192 	  abort ();
193 
194 	q = u.buf;
195 	for (i = 0; i < off; i++, q++)
196 	  if (*q != 'a')
197 	    abort ();
198 
199 	for (i = 0; i < len; i++, q++)
200 	  if (*q != '\0')
201 	    abort ();
202 
203 	for (i = 0; i < MAX_EXTRA; i++, q++)
204 	  if (*q != 'a')
205 	    abort ();
206 
207 	p = memset (u.buf + off, A, len);
208 	if (p != u.buf + off)
209 	  abort ();
210 
211 	q = u.buf;
212 	for (i = 0; i < off; i++, q++)
213 	  if (*q != 'a')
214 	    abort ();
215 
216 	for (i = 0; i < len; i++, q++)
217 	  if (*q != 'A')
218 	    abort ();
219 
220 	for (i = 0; i < MAX_EXTRA; i++, q++)
221 	  if (*q != 'a')
222 	    abort ();
223 
224 	p = memset (u.buf + off, 'B', len);
225 	if (p != u.buf + off)
226 	  abort ();
227 
228 	q = u.buf;
229 	for (i = 0; i < off; i++, q++)
230 	  if (*q != 'a')
231 	    abort ();
232 
233 	for (i = 0; i < len; i++, q++)
234 	  if (*q != 'B')
235 	    abort ();
236 
237 	for (i = 0; i < MAX_EXTRA; i++, q++)
238 	  if (*q != 'a')
239 	    abort ();
240       }
241 }
242 
243 static union {
244   char buf[MAX_LENGTH2];
245   long long align_int;
246   long double align_fp;
247 } u2;
248 
reset()249 void reset ()
250 {
251   int i;
252 
253   for (i = 0; i < MAX_LENGTH2; i++)
254     u2.buf[i] = 'a';
255 }
256 
check(int off,int len,int ch)257 void check (int off, int len, int ch)
258 {
259   char *q;
260   int i;
261 
262   q = u2.buf;
263   for (i = 0; i < off; i++, q++)
264     if (*q != 'a')
265       abort ();
266 
267   for (i = 0; i < len; i++, q++)
268     if (*q != ch)
269       abort ();
270 
271   for (i = 0; i < MAX_EXTRA; i++, q++)
272     if (*q != 'a')
273       abort ();
274 }
275 
276 void
277 __attribute__((noinline))
test5(void)278 test5 (void)
279 {
280   int off;
281   char *p;
282 
283   /* len == 1 */
284   for (off = 0; off < MAX_OFFSET; off++)
285     {
286       reset ();
287 
288       p = memset (u2.buf + off, '\0', 1);
289       if (p != u2.buf + off) abort ();
290       check (off, 1, '\0');
291 
292       p = memset (u2.buf + off, A, 1);
293       if (p != u2.buf + off) abort ();
294       check (off, 1, 'A');
295 
296       p = memset (u2.buf + off, 'B', 1);
297       if (p != u2.buf + off) abort ();
298       check (off, 1, 'B');
299     }
300 
301   /* len == 2 */
302   for (off = 0; off < MAX_OFFSET; off++)
303     {
304       reset ();
305 
306       p = memset (u2.buf + off, '\0', 2);
307       if (p != u2.buf + off) abort ();
308       check (off, 2, '\0');
309 
310       p = memset (u2.buf + off, A, 2);
311       if (p != u2.buf + off) abort ();
312       check (off, 2, 'A');
313 
314       p = memset (u2.buf + off, 'B', 2);
315       if (p != u2.buf + off) abort ();
316       check (off, 2, 'B');
317     }
318 
319   /* len == 3 */
320   for (off = 0; off < MAX_OFFSET; off++)
321     {
322       reset ();
323 
324       p = memset (u2.buf + off, '\0', 3);
325       if (p != u2.buf + off) abort ();
326       check (off, 3, '\0');
327 
328       p = memset (u2.buf + off, A, 3);
329       if (p != u2.buf + off) abort ();
330       check (off, 3, 'A');
331 
332       p = memset (u2.buf + off, 'B', 3);
333       if (p != u2.buf + off) abort ();
334       check (off, 3, 'B');
335     }
336 
337   /* len == 4 */
338   for (off = 0; off < MAX_OFFSET; off++)
339     {
340       reset ();
341 
342       p = memset (u2.buf + off, '\0', 4);
343       if (p != u2.buf + off) abort ();
344       check (off, 4, '\0');
345 
346       p = memset (u2.buf + off, A, 4);
347       if (p != u2.buf + off) abort ();
348       check (off, 4, 'A');
349 
350       p = memset (u2.buf + off, 'B', 4);
351       if (p != u2.buf + off) abort ();
352       check (off, 4, 'B');
353     }
354 
355   /* len == 5 */
356   for (off = 0; off < MAX_OFFSET; off++)
357     {
358       reset ();
359 
360       p = memset (u2.buf + off, '\0', 5);
361       if (p != u2.buf + off) abort ();
362       check (off, 5, '\0');
363 
364       p = memset (u2.buf + off, A, 5);
365       if (p != u2.buf + off) abort ();
366       check (off, 5, 'A');
367 
368       p = memset (u2.buf + off, 'B', 5);
369       if (p != u2.buf + off) abort ();
370       check (off, 5, 'B');
371     }
372 
373   /* len == 6 */
374   for (off = 0; off < MAX_OFFSET; off++)
375     {
376       reset ();
377 
378       p = memset (u2.buf + off, '\0', 6);
379       if (p != u2.buf + off) abort ();
380       check (off, 6, '\0');
381 
382       p = memset (u2.buf + off, A, 6);
383       if (p != u2.buf + off) abort ();
384       check (off, 6, 'A');
385 
386       p = memset (u2.buf + off, 'B', 6);
387       if (p != u2.buf + off) abort ();
388       check (off, 6, 'B');
389     }
390 
391   /* len == 7 */
392   for (off = 0; off < MAX_OFFSET; off++)
393     {
394       reset ();
395 
396       p = memset (u2.buf + off, '\0', 7);
397       if (p != u2.buf + off) abort ();
398       check (off, 7, '\0');
399 
400       p = memset (u2.buf + off, A, 7);
401       if (p != u2.buf + off) abort ();
402       check (off, 7, 'A');
403 
404       p = memset (u2.buf + off, 'B', 7);
405       if (p != u2.buf + off) abort ();
406       check (off, 7, 'B');
407     }
408 
409   /* len == 8 */
410   for (off = 0; off < MAX_OFFSET; off++)
411     {
412       reset ();
413 
414       p = memset (u2.buf + off, '\0', 8);
415       if (p != u2.buf + off) abort ();
416       check (off, 8, '\0');
417 
418       p = memset (u2.buf + off, A, 8);
419       if (p != u2.buf + off) abort ();
420       check (off, 8, 'A');
421 
422       p = memset (u2.buf + off, 'B', 8);
423       if (p != u2.buf + off) abort ();
424       check (off, 8, 'B');
425     }
426 
427   /* len == 9 */
428   for (off = 0; off < MAX_OFFSET; off++)
429     {
430       reset ();
431 
432       p = memset (u2.buf + off, '\0', 9);
433       if (p != u2.buf + off) abort ();
434       check (off, 9, '\0');
435 
436       p = memset (u2.buf + off, A, 9);
437       if (p != u2.buf + off) abort ();
438       check (off, 9, 'A');
439 
440       p = memset (u2.buf + off, 'B', 9);
441       if (p != u2.buf + off) abort ();
442       check (off, 9, 'B');
443     }
444 
445   /* len == 10 */
446   for (off = 0; off < MAX_OFFSET; off++)
447     {
448       reset ();
449 
450       p = memset (u2.buf + off, '\0', 10);
451       if (p != u2.buf + off) abort ();
452       check (off, 10, '\0');
453 
454       p = memset (u2.buf + off, A, 10);
455       if (p != u2.buf + off) abort ();
456       check (off, 10, 'A');
457 
458       p = memset (u2.buf + off, 'B', 10);
459       if (p != u2.buf + off) abort ();
460       check (off, 10, 'B');
461     }
462 
463   /* len == 11 */
464   for (off = 0; off < MAX_OFFSET; off++)
465     {
466       reset ();
467 
468       p = memset (u2.buf + off, '\0', 11);
469       if (p != u2.buf + off) abort ();
470       check (off, 11, '\0');
471 
472       p = memset (u2.buf + off, A, 11);
473       if (p != u2.buf + off) abort ();
474       check (off, 11, 'A');
475 
476       p = memset (u2.buf + off, 'B', 11);
477       if (p != u2.buf + off) abort ();
478       check (off, 11, 'B');
479     }
480 
481   /* len == 12 */
482   for (off = 0; off < MAX_OFFSET; off++)
483     {
484       reset ();
485 
486       p = memset (u2.buf + off, '\0', 12);
487       if (p != u2.buf + off) abort ();
488       check (off, 12, '\0');
489 
490       p = memset (u2.buf + off, A, 12);
491       if (p != u2.buf + off) abort ();
492       check (off, 12, 'A');
493 
494       p = memset (u2.buf + off, 'B', 12);
495       if (p != u2.buf + off) abort ();
496       check (off, 12, 'B');
497     }
498 
499   /* len == 13 */
500   for (off = 0; off < MAX_OFFSET; off++)
501     {
502       reset ();
503 
504       p = memset (u2.buf + off, '\0', 13);
505       if (p != u2.buf + off) abort ();
506       check (off, 13, '\0');
507 
508       p = memset (u2.buf + off, A, 13);
509       if (p != u2.buf + off) abort ();
510       check (off, 13, 'A');
511 
512       p = memset (u2.buf + off, 'B', 13);
513       if (p != u2.buf + off) abort ();
514       check (off, 13, 'B');
515     }
516 
517   /* len == 14 */
518   for (off = 0; off < MAX_OFFSET; off++)
519     {
520       reset ();
521 
522       p = memset (u2.buf + off, '\0', 14);
523       if (p != u2.buf + off) abort ();
524       check (off, 14, '\0');
525 
526       p = memset (u2.buf + off, A, 14);
527       if (p != u2.buf + off) abort ();
528       check (off, 14, 'A');
529 
530       p = memset (u2.buf + off, 'B', 14);
531       if (p != u2.buf + off) abort ();
532       check (off, 14, 'B');
533     }
534 
535   /* len == 15 */
536   for (off = 0; off < MAX_OFFSET; off++)
537     {
538       reset ();
539 
540       p = memset (u2.buf + off, '\0', 15);
541       if (p != u2.buf + off) abort ();
542       check (off, 15, '\0');
543 
544       p = memset (u2.buf + off, A, 15);
545       if (p != u2.buf + off) abort ();
546       check (off, 15, 'A');
547 
548       p = memset (u2.buf + off, 'B', 15);
549       if (p != u2.buf + off) abort ();
550       check (off, 15, 'B');
551     }
552 }
553 
554 void
555 __attribute__((noinline))
test6(void)556 test6 (void)
557 {
558   int len;
559   char *p;
560 
561   /* off == 0 */
562   for (len = 0; len < MAX_COPY2; len++)
563     {
564       reset ();
565 
566       p = memset (u2.buf, '\0', len);
567       if (p != u2.buf) abort ();
568       check (0, len, '\0');
569 
570       p = memset (u2.buf, A, len);
571       if (p != u2.buf) abort ();
572       check (0, len, 'A');
573 
574       p = memset (u2.buf, 'B', len);
575       if (p != u2.buf) abort ();
576       check (0, len, 'B');
577     }
578 
579   /* off == 1 */
580   for (len = 0; len < MAX_COPY2; len++)
581     {
582       reset ();
583 
584       p = memset (u2.buf+1, '\0', len);
585       if (p != u2.buf+1) abort ();
586       check (1, len, '\0');
587 
588       p = memset (u2.buf+1, A, len);
589       if (p != u2.buf+1) abort ();
590       check (1, len, 'A');
591 
592       p = memset (u2.buf+1, 'B', len);
593       if (p != u2.buf+1) abort ();
594       check (1, len, 'B');
595     }
596 
597   /* off == 2 */
598   for (len = 0; len < MAX_COPY2; len++)
599     {
600       reset ();
601 
602       p = memset (u2.buf+2, '\0', len);
603       if (p != u2.buf+2) abort ();
604       check (2, len, '\0');
605 
606       p = memset (u2.buf+2, A, len);
607       if (p != u2.buf+2) abort ();
608       check (2, len, 'A');
609 
610       p = memset (u2.buf+2, 'B', len);
611       if (p != u2.buf+2) abort ();
612       check (2, len, 'B');
613     }
614 
615   /* off == 3 */
616   for (len = 0; len < MAX_COPY2; len++)
617     {
618       reset ();
619 
620       p = memset (u2.buf+3, '\0', len);
621       if (p != u2.buf+3) abort ();
622       check (3, len, '\0');
623 
624       p = memset (u2.buf+3, A, len);
625       if (p != u2.buf+3) abort ();
626       check (3, len, 'A');
627 
628       p = memset (u2.buf+3, 'B', len);
629       if (p != u2.buf+3) abort ();
630       check (3, len, 'B');
631     }
632 
633   /* off == 4 */
634   for (len = 0; len < MAX_COPY2; len++)
635     {
636       reset ();
637 
638       p = memset (u2.buf+4, '\0', len);
639       if (p != u2.buf+4) abort ();
640       check (4, len, '\0');
641 
642       p = memset (u2.buf+4, A, len);
643       if (p != u2.buf+4) abort ();
644       check (4, len, 'A');
645 
646       p = memset (u2.buf+4, 'B', len);
647       if (p != u2.buf+4) abort ();
648       check (4, len, 'B');
649     }
650 
651   /* off == 5 */
652   for (len = 0; len < MAX_COPY2; len++)
653     {
654       reset ();
655 
656       p = memset (u2.buf+5, '\0', len);
657       if (p != u2.buf+5) abort ();
658       check (5, len, '\0');
659 
660       p = memset (u2.buf+5, A, len);
661       if (p != u2.buf+5) abort ();
662       check (5, len, 'A');
663 
664       p = memset (u2.buf+5, 'B', len);
665       if (p != u2.buf+5) abort ();
666       check (5, len, 'B');
667     }
668 
669   /* off == 6 */
670   for (len = 0; len < MAX_COPY2; len++)
671     {
672       reset ();
673 
674       p = memset (u2.buf+6, '\0', len);
675       if (p != u2.buf+6) abort ();
676       check (6, len, '\0');
677 
678       p = memset (u2.buf+6, A, len);
679       if (p != u2.buf+6) abort ();
680       check (6, len, 'A');
681 
682       p = memset (u2.buf+6, 'B', len);
683       if (p != u2.buf+6) abort ();
684       check (6, len, 'B');
685     }
686 
687   /* off == 7 */
688   for (len = 0; len < MAX_COPY2; len++)
689     {
690       reset ();
691 
692       p = memset (u2.buf+7, '\0', len);
693       if (p != u2.buf+7) abort ();
694       check (7, len, '\0');
695 
696       p = memset (u2.buf+7, A, len);
697       if (p != u2.buf+7) abort ();
698       check (7, len, 'A');
699 
700       p = memset (u2.buf+7, 'B', len);
701       if (p != u2.buf+7) abort ();
702       check (7, len, 'B');
703     }
704 }
705 
706 void
main_test(void)707 main_test (void)
708 {
709 #ifndef __OPTIMIZE__
710   /* Object size checking is only intended for -O[s123].  */
711   return;
712 #endif
713   __asm ("" : "=r" (l1) : "0" (l1));
714   s4 = buffer;
715   test1 ();
716   test2 ();
717   test3 ();
718   test4 ();
719   test5 ();
720   test6 ();
721 }
722