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