1 /* https://bugs.kde.org/show_bug.cgi?id=309921 */
2
3 #define _XOPEN_SOURCE 600 /* for posix_memalign() */
4
5 #include "../../memcheck.h"
6
7 #include <stdio.h>
8 #include <assert.h>
9 #include <string.h>
10 #include <stdlib.h>
11
12 /* Exercise pcmpistri instruction in a realistic way. */
aligned_strlen(const char * const s)13 int aligned_strlen(const char *const s)
14 {
15 assert(((unsigned long)s & 0x0F) == 0);
16
17 const char *p = s;
18
19 /* volatile asm and "memory" clobber are needed here, since we
20 access memory in ways we cannot describe to GCC. */
21 __asm__ __volatile__ ("\n1:\n"
22 "\tmovdqa (%0),%%xmm6\n"
23 "\tpcmpistri $0x3a,%%xmm6,%%xmm6\n"
24 "\tjc 2f\n"
25 "\tadd $0x10,%0\n"
26 "\tjmp 1b\n"
27 "2:\n"
28 "\tadd %%rcx,%0\n"
29 : "=p" (p) : "0" (p) : "xmm6", "rcx", "cc", "memory");
30
31 return p-s;
32 }
33
34 /* Compute strlen(s). Arrange for result to be valid or invalid
35 according to second argument. */
test_strlen(const char * const s,int valid)36 int test_strlen(const char *const s, int valid)
37 {
38 /* len = length of string including trailing null */
39 const size_t len = strlen(s) + 1;
40 const size_t roundup = ((len+15)/16)*16;
41 int result = -1;
42
43 void *space;
44 posix_memalign(&space, 16, roundup);
45 memset(space, 'x', roundup);
46 memcpy(space, s, len);
47
48 const char *const s_copy = space;
49 const unsigned char ff = 0xFF;
50 if (valid) {
51 /* Mark all bytes beyond the null as invalid. */
52 size_t i;
53 for (i=len ; i < roundup ; ++i)
54 (void)VALGRIND_SET_VBITS(&s_copy[i], &ff, 1);
55 }
56 else {
57 /* Mark the null byte itself as invalid. */
58 assert(len > 0);
59 (void)VALGRIND_SET_VBITS(&s_copy[len-1], &ff, 1);
60 }
61
62 result = aligned_strlen(s_copy);
63
64 free(space);
65
66 return result;
67 }
68
doit(const char * const s)69 void doit(const char *const s)
70 {
71 printf("strlen(\"%s\")=%d\n", s, test_strlen(s, 1));
72
73 fprintf(stderr, "strlen(\"%s\")=%s\n", s,
74 test_strlen(s, 0) ? "true" : "false");
75 }
76
main(int argc,char * argv[])77 int main(int argc, char *argv[])
78 {
79 doit("");
80 doit("a");
81 doit("ab");
82 doit("abc");
83 doit("abcd");
84 doit("abcde");
85 doit("abcdef");
86 doit("abcdefg");
87 /* 8 */
88 doit("abcdefgh");
89 doit("abcdefghi");
90 doit("abcdefghij");
91 doit("abcdefghijk");
92 doit("abcdefghijkl");
93 doit("abcdefghijklm");
94 doit("abcdefghijklmn");
95 doit("abcdefghijklmno");
96 /* 16 */
97 doit("abcdefghijklmnop");
98 doit("abcdefghijklmnopq");
99 doit("abcdefghijklmnopqr");
100 doit("abcdefghijklmnopqrs");
101 doit("abcdefghijklmnopqrst");
102 doit("abcdefghijklmnopqrstu");
103 doit("abcdefghijklmnopqrstuv");
104 doit("abcdefghijklmnopqrstuvw");
105 doit("abcdefghijklmnopqrstuwvx");
106 doit("abcdefghijklmnopqrstuwvxy");
107 doit("abcdefghijklmnopqrstuwvxyz");
108 /* 255 */
109 doit("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
110 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
111 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
112 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
113 /* 256 */
114 doit("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
115 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
116 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
117 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
118 return 0;
119 }
120