1 /* The z13 stpcpy implementation plays some alignment tricks for good
2    performance.  This test tries to make sure it works correctly and
3    does not access bytes beyond the source and destination
4    strings.  */
5 
6 /* { dg-do run } */
7 /* { dg-require-effective-target s390_vx } */
8 /* { dg-options "-O3 -mzarch -march=z13" } */
9 
10 #include <stdio.h>
11 #include <sys/mman.h>
12 
13 #define PAGE_SIZE 4096
14 
15 struct {
16   char unused[PAGE_SIZE - 32];
17   char m32[15]; /* page bndry - 32 */
18   char m17[1];
19   char m16[1];
20   char m15[14];
21   char m1[1];
22   char next_page[PAGE_SIZE];
23 } s, d __attribute__((aligned(PAGE_SIZE)));
24 
25 char *__attribute__((noinline))
my_stpcpy(char * dest,const char * src)26 my_stpcpy(char *dest, const char *src)
27 {
28   return __builtin_stpcpy (dest, src);
29 }
30 
31 void __attribute__ ((noinline))
check(char * dest,char * src,size_t len)32 check (char *dest, char *src, size_t len)
33 {
34   char *result;
35 
36   result = my_stpcpy (dest, src);
37   if (result != dest + len)
38     __builtin_abort ();
39   if (__builtin_memcmp (src, dest, len) != 0)
40     __builtin_abort ();
41 }
42 
43 int
main()44 main ()
45 {
46   char *src[5] = { s.m32, s.m17, s.m16, s.m15, s.m1 };
47   char *dst[5] = { d.m32, d.m17, d.m16, d.m15, d.m1 };
48   int len[8] = { 33, 32, 31, 17, 16, 15, 1, 0 };
49   int i, j, k;
50   char backup;
51 
52   for (i = 0; i < sizeof (s); i++)
53     ((char*)&s)[i] = i % 26 + 97;
54 
55   for (i = 0; i < 5; i++)
56     for (j = 0; j < 5; j++)
57       for (k = 0; k < 8; k++)
58 	{
59 	  backup = src[j][len[k]];
60 	  src[j][len[k]] = 0;
61 	  __builtin_memset (&d, 0, sizeof (d));
62 	  check (dst[i], src[j], len[k]);
63 	  src[j][len[k]] = backup;
64 	}
65 
66   /* Make all source strings end before the page boundary.  */
67   backup = s.m1[0];
68   s.m1[0] = 0;
69 
70   if (mprotect (&s.next_page, PAGE_SIZE, PROT_NONE) == -1)
71     perror ("mprotect src");
72 
73   for (i = 0; i < 5; i++)
74     for (j = 0; j < 5; j++)
75       check (dst[i], src[j],
76 	     PAGE_SIZE - ((unsigned long)src[j] & ((1UL << 12) - 1)) - 1);
77 
78   if (mprotect (&s.next_page, PAGE_SIZE, PROT_READ | PROT_WRITE) == -1)
79     perror ("mprotect src");
80 
81   s.m1[0] = backup;
82 
83   if (mprotect (&d.next_page, PAGE_SIZE, PROT_NONE) == -1)
84     perror ("mprotect dst");
85 
86   for (i = 0; i < 5; i++)
87     for (j = 0; j < 5; j++)
88       {
89 	int len = PAGE_SIZE - ((unsigned long)dst[i] & ((1UL << 12) - 1)) - 1;
90 	char backup = src[j][len];
91 
92 	src[j][len] = 0;
93 	__builtin_memset (&d, 0,
94 			  (unsigned long)&d.next_page - (unsigned long)&d);
95 	check (dst[i], src[j], len);
96 	src[j][len] = backup;
97       }
98 
99   return 0;
100 }
101