/* https://bugs.kde.org/show_bug.cgi?id=309921 */ #define _XOPEN_SOURCE 600 /* for posix_memalign() */ #include "../../memcheck.h" #include <stdio.h> #include <assert.h> #include <string.h> #include <stdlib.h> /* Exercise pcmpistri instruction in a realistic way. */ int aligned_strlen(const char *const s) { assert(((unsigned long)s & 0x0F) == 0); const char *p = s; /* volatile asm and "memory" clobber are needed here, since we access memory in ways we cannot describe to GCC. */ __asm__ __volatile__ ("\n1:\n" "\tmovdqa (%0),%%xmm6\n" "\tpcmpistri $0x3a,%%xmm6,%%xmm6\n" "\tjc 2f\n" "\tadd $0x10,%0\n" "\tjmp 1b\n" "2:\n" "\tadd %%rcx,%0\n" : "=p" (p) : "0" (p) : "xmm6", "rcx", "cc", "memory"); return p-s; } /* Compute strlen(s). Arrange for result to be valid or invalid according to second argument. */ int test_strlen(const char *const s, int valid) { /* len = length of string including trailing null */ const size_t len = strlen(s) + 1; const size_t roundup = ((len+15)/16)*16; int result = -1; void *space; posix_memalign(&space, 16, roundup); memset(space, 'x', roundup); memcpy(space, s, len); const char *const s_copy = space; const unsigned char ff = 0xFF; if (valid) { /* Mark all bytes beyond the null as invalid. */ size_t i; for (i=len ; i < roundup ; ++i) (void)VALGRIND_SET_VBITS(&s_copy[i], &ff, 1); } else { /* Mark the null byte itself as invalid. */ assert(len > 0); (void)VALGRIND_SET_VBITS(&s_copy[len-1], &ff, 1); } result = aligned_strlen(s_copy); free(space); return result; } void doit(const char *const s) { printf("strlen(\"%s\")=%d\n", s, test_strlen(s, 1)); fprintf(stderr, "strlen(\"%s\")=%s\n", s, test_strlen(s, 0) ? "true" : "false"); } int main(int argc, char *argv[]) { doit(""); doit("a"); doit("ab"); doit("abc"); doit("abcd"); doit("abcde"); doit("abcdef"); doit("abcdefg"); /* 8 */ doit("abcdefgh"); doit("abcdefghi"); doit("abcdefghij"); doit("abcdefghijk"); doit("abcdefghijkl"); doit("abcdefghijklm"); doit("abcdefghijklmn"); doit("abcdefghijklmno"); /* 16 */ doit("abcdefghijklmnop"); doit("abcdefghijklmnopq"); doit("abcdefghijklmnopqr"); doit("abcdefghijklmnopqrs"); doit("abcdefghijklmnopqrst"); doit("abcdefghijklmnopqrstu"); doit("abcdefghijklmnopqrstuv"); doit("abcdefghijklmnopqrstuvw"); doit("abcdefghijklmnopqrstuwvx"); doit("abcdefghijklmnopqrstuwvxy"); doit("abcdefghijklmnopqrstuwvxyz"); /* 255 */ doit("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); /* 256 */ doit("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); return 0; }