1/* Copyright (C) 2004, 2005  Free Software Foundation.
2
3   Ensure builtin __memset_chk performs correctly.  */
4
5extern void abort (void);
6typedef __SIZE_TYPE__ size_t;
7extern size_t strlen(const char *);
8extern void *memcpy (void *, const void *, size_t);
9extern void *memset (void *, int, size_t);
10extern int memcmp (const void *, const void *, size_t);
11
12#include "chk.h"
13
14char buffer[32];
15int argc = 1;
16size_t l1 = 1;
17char *s3 = "FGH";
18char *s4;
19
20void
21__attribute__((noinline))
22test1 (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.  */
51void
52__attribute__((noinline))
53test2 (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.  */
123void
124__attribute__((noinline))
125test3 (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
169static union {
170  char buf[MAX_LENGTH];
171  long long align_int;
172  long double align_fp;
173} u;
174
175char A = 'A';
176
177void
178__attribute__((noinline))
179test4 (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
243static union {
244  char buf[MAX_LENGTH2];
245  long long align_int;
246  long double align_fp;
247} u2;
248
249void reset ()
250{
251  int i;
252
253  for (i = 0; i < MAX_LENGTH2; i++)
254    u2.buf[i] = 'a';
255}
256
257void 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
276void
277__attribute__((noinline))
278test5 (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
554void
555__attribute__((noinline))
556test6 (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
706void
707main_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