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. */ 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. */ 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 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 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