1 /*
2  * __mtag_tag_zero_region test.
3  *
4  * Copyright (c) 2021, Arm Limited.
5  * SPDX-License-Identifier: MIT
6  */
7 
8 #if __ARM_FEATURE_MEMORY_TAGGING && WANT_MTE_TEST
9 #include <stdint.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include "mte.h"
14 #include "stringlib.h"
15 #include "stringtest.h"
16 
17 static void
18 mtag_quoteat (const char *prefix, void *p, int len, int at)
19 {
20   /* Print tag, untag and quote the context.  */
21   printf ("location: %p\n", __arm_mte_get_tag ((char *) p + at));
22   untag_buffer (p, len, 1);
23   p = untag_pointer (p);
24   quoteat (prefix, p, len, at);
25 }
26 
27 #define F(x) {#x, x},
28 
29 static const struct fun
30 {
31   const char *name;
32   void *(*fun) (void *s, size_t n);
33 } funtab[] = {
34 // clang-format off
35 #if __aarch64__
36   F(__mtag_tag_zero_region)
37 #endif
38   {0, 0}
39   // clang-format on
40 };
41 #undef F
42 
43 #define A 64
44 #define LEN 250000
45 static unsigned char *sbuf;
46 
47 static void *
48 alignup (void *p)
49 {
50   return (void *) (((uintptr_t) p + A - 1) & -A);
51 }
52 
53 static void
54 test (const struct fun *fun, int salign, int len)
55 {
56   unsigned char *src = alignup (sbuf);
57   unsigned char *s = src + salign;
58   void *p;
59   int i;
60 
61   if (err_count >= ERR_LIMIT)
62     return;
63   if (len > LEN || salign >= A)
64     abort ();
65   for (i = 0; i < len + 2 * A; i++)
66     src[i] = '?';
67   for (i = 0; i < len; i++)
68     s[i] = 'a' + i % 23;
69 
70   src = tag_buffer (src, len + 2 * A, 1);
71   s = src + salign;
72   /* Use different tag.  */
73   s = __arm_mte_increment_tag (s, 1);
74   p = fun->fun (s, len);
75 
76   if (p != s)
77     ERR ("%s(%p,..) returned %p\n", fun->name, s, p);
78 
79   for (i = 0; i < salign; i++)
80     {
81       if (src[i] != '?')
82 	{
83 	  ERR ("%s(align %d, %d) failed\n", fun->name, salign, len);
84 	  mtag_quoteat ("got head", src, len + 2 * A, i);
85 	  return;
86 	}
87     }
88 
89   for (; i < salign + len; i++)
90     {
91       if (s[i - salign] != 0)
92 	{
93 	  ERR ("%s(align %d, %d) failed\n", fun->name, salign, len);
94 	  mtag_quoteat ("got body", src, len + 2 * A, i);
95 	  return;
96 	}
97     }
98 
99   for (; i < len + 2 * A; i++)
100     {
101       if (src[i] != '?')
102 	{
103 	  ERR ("%s(align %d, %d) failed\n", fun->name, salign, len);
104 	  mtag_quoteat ("got tail", src, len + 2 * A, i);
105 	  return;
106 	}
107     }
108 
109   untag_buffer (src, len + 2 * A, 1);
110 }
111 
112 int
113 main ()
114 {
115   if (!mte_enabled ())
116     return 0;
117 
118   sbuf = mte_mmap (LEN + 3 * A);
119   int r = 0;
120   for (int i = 0; funtab[i].name; i++)
121     {
122       err_count = 0;
123       for (int s = 0; s < A; s += 16)
124 	{
125 	  int n;
126 	  for (n = 0; n < 200; n += 16)
127 	    {
128 	      test (funtab + i, s, n);
129 	    }
130 	  for (; n < LEN; n *= 2)
131 	    {
132 	      test (funtab + i, s, n);
133 	    }
134 	}
135       printf ("%s %s\n", err_count ? "FAIL" : "PASS", funtab[i].name);
136       if (err_count)
137 	r = -1;
138     }
139   return r;
140 }
141 #else
142 int
143 main ()
144 {
145   return 0;
146 }
147 #endif
148