Home | History | Annotate | Download | only in libc_test
      1 /*
      2 ** Copyright 2013 The Android Open Source Project
      3 **
      4 ** Licensed under the Apache License, Version 2.0 (the "License");
      5 ** you may not use this file except in compliance with the License.
      6 ** You may obtain a copy of the License at
      7 **
      8 **     http://www.apache.org/licenses/LICENSE-2.0
      9 **
     10 ** Unless required by applicable law or agreed to in writing, software
     11 ** distributed under the License is distributed on an "AS IS" BASIS,
     12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 ** See the License for the specific language governing permissions and
     14 ** limitations under the License.
     15 */
     16 
     17 #include <stdio.h>
     18 #include <stdlib.h>
     19 #include <unistd.h>
     20 #include <sys/mman.h>
     21 
     22 // Put any local test functions into the extern below.
     23 extern "C" {
     24 }
     25 
     26 #define FENCEPOST_LENGTH          8
     27 
     28 #define MAX_MEMCPY_TEST_SIZE      2048
     29 #define MAX_MEMCPY_BUFFER_SIZE    (3 * MAX_MEMCPY_TEST_SIZE)
     30 
     31 #define MAX_MEMSET_TEST_SIZE      2048
     32 #define MAX_MEMSET_BUFFER_SIZE    (3 * MAX_MEMSET_TEST_SIZE)
     33 
     34 #define MAX_STRING_TEST_SIZE      1024
     35 #define MAX_STRING_BUFFER_SIZE    (3 * MAX_STRING_TEST_SIZE)
     36 
     37 #define MAX_STRCAT_DST_SIZE       32
     38 
     39 const int kStringAligns[][4] = {
     40   // All zeroes to use the values returned from malloc.
     41   { 0, 0, 0, 0 },
     42 
     43   { 1, 0, 1, 0 },
     44   { 2, 0, 2, 0 },
     45   { 4, 0, 4, 0 },
     46   { 8, 0, 8, 0 },
     47 
     48   { 8, 0, 4, 0 },
     49   { 4, 0, 8, 0 },
     50 
     51   { 8, 0, 8, 1 },
     52   { 8, 0, 8, 2 },
     53   { 8, 0, 8, 3 },
     54   { 8, 1, 8, 0 },
     55   { 8, 2, 8, 0 },
     56   { 8, 3, 8, 0 },
     57 
     58   { 4, 0, 4, 1 },
     59   { 4, 0, 4, 2 },
     60   { 4, 0, 4, 3 },
     61   { 4, 1, 4, 0 },
     62   { 4, 2, 4, 0 },
     63   { 4, 3, 4, 0 },
     64 };
     65 
     66 #define STRING_ALIGN_LEN  (sizeof(kStringAligns)/sizeof(int[4]))
     67 
     68 // Return a pointer into the current string with the specified alignment.
     69 void *getAlignedPtr(void *orig_ptr, int alignment, int or_mask) {
     70   uint64_t ptr = reinterpret_cast<uint64_t>(orig_ptr);
     71   if (alignment > 0) {
     72       // When setting the alignment, set it to exactly the alignment chosen.
     73       // The pointer returned will be guaranteed not to be aligned to anything
     74       // more than that.
     75       ptr += alignment - (ptr & (alignment - 1));
     76       ptr |= alignment | or_mask;
     77   }
     78 
     79   return reinterpret_cast<void*>(ptr);
     80 }
     81 
     82 char *setString(char *str, size_t size) {
     83   for (size_t i = 0; i < size; i++) {
     84     str[i] = (char)(32 + (i % 96));
     85   }
     86   str[size] = '\0';
     87 
     88   return str;
     89 }
     90 
     91 char *allocateString() {
     92   char *str = reinterpret_cast<char*>(malloc(MAX_STRING_BUFFER_SIZE+1));
     93   if (!str) {
     94     return NULL;
     95   }
     96 
     97   return setString(str, MAX_STRING_BUFFER_SIZE);
     98 }
     99 
    100 void setFencepost(uint8_t *buffer) {
    101   for (int i = 0; i < FENCEPOST_LENGTH; i += 2) {
    102     buffer[i] = 0xde;
    103     buffer[i+1] = 0xad;
    104   }
    105 }
    106 
    107 bool verifyFencepost(uint8_t *buffer) {
    108   for (int i = 0; i < FENCEPOST_LENGTH; i += 2) {
    109     if (buffer[i] != 0xde || buffer[i+1] != 0xad) {
    110       uint8_t expected_value;
    111       if (buffer[i] == 0xde) {
    112         i++;
    113         expected_value = 0xad;
    114       } else {
    115         expected_value = 0xde;
    116       }
    117       printf("    mismatch at fencepost[%d], expected %d found %d\n",
    118              i, expected_value, buffer[i]);
    119       return false;
    120     }
    121   }
    122   return true;
    123 }
    124 
    125 bool doStrcmpExpectEqual(char *string1, char *string2, const int align[4],
    126                          int (*test_strcmp)(const char *s1, const char *s2),
    127                          bool verbose) {
    128   char *align_str1 = (char*)getAlignedPtr(string1, align[0], align[1]);
    129   char *align_str2 = (char*)getAlignedPtr(string2, align[2], align[3]);
    130 
    131   for (size_t i = 0; i < MAX_STRING_TEST_SIZE; i++) {
    132     for (size_t j = 0; j < i; j++) {
    133       align_str1[j] = (char)(32 + (j % 96));
    134       align_str2[j] = align_str1[j];
    135     }
    136     align_str1[i] = '\0';
    137     align_str2[i] = '\0';
    138 
    139     // Set the characters after the string terminates to different values
    140     // to verify that the strcmp is not over checking.
    141     for (size_t j = i+1; j < i+64; j++) {
    142       align_str1[j] = (char)(32 + j);
    143       align_str2[j] = (char)(40 + j);
    144     }
    145 
    146     if (verbose) {
    147       printf("Testing size %d, align_str1=%p[%d,%d], align_str2=%p[%d,%d]\n",
    148              i, align_str1, align[0], align[1], align_str2, align[2], align[3]);
    149     }
    150 
    151     if (test_strcmp(align_str1, align_str2) != 0) {
    152       printf("    Failed at size %d, src1 %p, src2 %p\n",
    153              i, align_str1, align_str2);
    154       return false;
    155     }
    156   }
    157 
    158   return true;
    159 }
    160 
    161 bool doStrcmpExpectDiff(char *string1, char *string2, const int diff_align[2],
    162                         const int align[4], char diff_char,
    163                         int (*test_strcmp)(const char *s1, const char *s2),
    164                         bool verbose) {
    165   char *align_str1 = (char*)getAlignedPtr(string1, align[0], align[1]);
    166   char *align_str2 = (char*)getAlignedPtr(string2, align[2], align[3]);
    167 
    168   for (int i = 0; i < MAX_STRING_TEST_SIZE; i++) {
    169     // Use valid ascii characters, no unprintables characters.
    170     align_str1[i] = (char)(32 + (i % 96));
    171     if (align_str1[i] == diff_char) {
    172       // Assumes that one less than the diff character is still a valid
    173       // character.
    174       align_str1[i] = diff_char-1;
    175     }
    176     align_str2[i] = align_str1[i];
    177   }
    178   align_str1[MAX_STRING_TEST_SIZE] = '\0';
    179   align_str2[MAX_STRING_TEST_SIZE] = '\0';
    180 
    181   // Quick check to make sure that the strcmp knows that everything is
    182   // equal. If it's so broken that it already thinks the strings are
    183   // different, then there is no point running any of the other tests.
    184   if (test_strcmp(align_str1, align_str2) != 0) {
    185     printf("    strcmp is too broken to do difference testing.\n");
    186     return false;
    187   }
    188 
    189   // Get a pointer into the string at the specified alignment.
    190   char *bad = (char*)getAlignedPtr(align_str1+MAX_STRING_TEST_SIZE/2,
    191                                    diff_align[0], diff_align[1]);
    192 
    193   char saved_char = bad[0];
    194   bad[0] = diff_char;
    195 
    196   if (verbose) {
    197     printf("Testing difference, align_str1=%p[%d,%d], align_str2=%p[%d,%d]\n",
    198            align_str1, align[0], align[1], align_str2, align[2], align[3]);
    199   }
    200   if (test_strcmp(align_str1, align_str2) == 0) {
    201     printf("   Did not miscompare at size %d, src1 %p, src2 %p, diff %p\n",
    202            MAX_STRING_TEST_SIZE, align_str1, align_str2, bad);
    203     return false;
    204   }
    205   bad[0] = saved_char;
    206 
    207   // Re-verify that something hasn't gone horribly wrong.
    208   if (test_strcmp(align_str1, align_str2) != 0) {
    209     printf("   strcmp is too broken to do difference testing.\n");
    210     return false;
    211   }
    212 
    213   bad = (char*)getAlignedPtr(align_str2+MAX_STRING_TEST_SIZE/2, diff_align[0],
    214                              diff_align[1]);
    215   bad[0] = diff_char;
    216 
    217   if (verbose) {
    218     printf("Testing reverse difference, align_str1=%p[%d,%d], align_str2=%p[%d,%d]\n",
    219            align_str1, align[0], align[1], align_str2, align[2], align[3]);
    220   }
    221   if (test_strcmp(align_str1, align_str2) == 0) {
    222     printf("    Did not miscompare at size %d, src1 %p, src2 %p, diff %p\n",
    223            MAX_STRING_TEST_SIZE, align_str1, align_str2, bad);
    224     return false;
    225   }
    226 
    227   return true;
    228 }
    229 
    230 bool doStrcmpCheckRead(int (*test_strcmp)(const char *s1, const char *s2),
    231                        bool verbose) {
    232   // In order to verify that the strcmp is not reading past the end of the
    233   // string, create some strings that end near unreadable memory.
    234   long pagesize = sysconf(_SC_PAGE_SIZE);
    235   char *memory = (char*)memalign(pagesize, 2 * pagesize);
    236   if (memory == NULL) {
    237     perror("Unable to allocate memory.\n");
    238     return false;
    239   }
    240 
    241   // Make the second page unreadable and unwritable.
    242   if (mprotect(&memory[pagesize], pagesize, PROT_NONE) != 0) {
    243     perror("Unable to set protection of page.\n");
    244     return false;
    245   }
    246 
    247   size_t max_size = pagesize < MAX_STRING_TEST_SIZE ? pagesize-1 : MAX_STRING_TEST_SIZE;
    248   // Allocate an extra byte beyond the string terminator to allow us to
    249   // extend the string to be larger than our protected string.
    250   char *other_string = (char *)malloc(max_size+2);
    251   if (other_string == NULL) {
    252     perror("Unable to allocate memory.\n");
    253     return false;
    254   }
    255   char *string;
    256   for (size_t i = 0; i <= max_size; i++) {
    257     string = &memory[pagesize-i-1];
    258     for (size_t j = 0; j < i; j++) {
    259       other_string[j] = (char)(32 + (j % 96));
    260       string[j] = other_string[j];
    261     }
    262     other_string[i] = '\0';
    263     string[i] = '\0';
    264 
    265     if (verbose) {
    266       printf("Testing size %d, strings equal.\n", i);
    267     }
    268     if (test_strcmp(other_string, string) != 0) {
    269       printf("    Failed at size %d, src1 %p, src2 %p\n", i, other_string, string);
    270       return false;
    271     }
    272 
    273     if (verbose) {
    274       printf("Testing size %d, strings equal reverse strings.\n", i);
    275     }
    276     if (test_strcmp(string, other_string) != 0) {
    277       printf("    Failed at size %d, src1 %p, src2 %p\n", i, string, other_string);
    278       return false;
    279     }
    280 
    281     // Now make other_string longer than our protected string.
    282     other_string[i] = '1';
    283     other_string[i+1] = '\0';
    284 
    285     if (verbose) {
    286       printf("Testing size %d, strings not equal.\n", i);
    287     }
    288     if (test_strcmp(other_string, string) == 0) {
    289       printf("    Failed at size %d, src1 %p, src2 %p\n", i, other_string, string);
    290       return false;
    291     }
    292 
    293     if (verbose) {
    294       printf("Testing size %d, strings not equal reverse the strings.\n", i);
    295     }
    296     if (test_strcmp(string, other_string) == 0) {
    297       printf("    Failed at size %d, src1 %p, src2 %p\n", i, string, other_string);
    298       return false;
    299     }
    300   }
    301   return true;
    302 }
    303 
    304 bool runStrcmpTest(int (*test_strcmp)(const char *s1, const char *s2),
    305                    bool verbose) {
    306   char *string1 = allocateString();
    307   char *string2 = allocateString();
    308   if (string1 == NULL || string2 == NULL) {
    309     perror("Unable to allocate memory.\n");
    310     return false;
    311   }
    312 
    313   printf("  Verifying equal sized strings at different alignments.\n");
    314   for (size_t i = 0; i < STRING_ALIGN_LEN; i++) {
    315     if (!doStrcmpExpectEqual(string1, string2, kStringAligns[i], test_strcmp,
    316                              verbose)) {
    317       return false;
    318     }
    319   }
    320 
    321   // Test the function finds strings with differences at specific locations.
    322   const int diff_aligns[][2] = {
    323     { 4, 0 },
    324     { 4, 1 },
    325     { 4, 2 },
    326     { 4, 3 },
    327     { 8, 0 },
    328     { 8, 1 },
    329     { 8, 2 },
    330     { 8, 3 },
    331   };
    332   printf("  Verifying different strings at different alignments.\n");
    333   for (size_t i = 0; i < sizeof(diff_aligns)/sizeof(int[2]); i++) {
    334     // First loop put the string terminator at the chosen alignment.
    335     for (size_t j = 0; j < STRING_ALIGN_LEN; j++) {
    336       if (!doStrcmpExpectDiff(string1, string2, diff_aligns[i],
    337                               kStringAligns[j], '\0', test_strcmp, verbose)) {
    338         return false;
    339       }
    340     }
    341     // Second loop put a different character at the chosen alignment.
    342     // This character is guaranteed not to be in the original string.
    343     for (size_t j = 0; j < STRING_ALIGN_LEN; j++) {
    344       if (!doStrcmpExpectDiff(string1, string2, diff_aligns[i],
    345                               kStringAligns[j], '\0', test_strcmp, verbose)) {
    346         return false;
    347       }
    348     }
    349   }
    350 
    351   printf("  Verifying strcmp does not read too many bytes.\n");
    352   if (!doStrcmpCheckRead(test_strcmp, verbose)) {
    353     return false;
    354   }
    355 
    356   printf("  All tests pass.\n");
    357 
    358   return true;
    359 }
    360 
    361 bool doStrlenCheck(size_t size, char *string, int align, int or_mask,
    362                    size_t (*test_strlen)(const char *), bool verbose) {
    363   char *aligned_string = reinterpret_cast<char*>(getAlignedPtr(string, align, or_mask));
    364   size_t len;
    365   if (verbose) {
    366     printf("Testing size %d, align=%p[%d,%d]\n", size, aligned_string, align, or_mask);
    367   }
    368 
    369   aligned_string[size] = '\0';
    370   len = test_strlen(aligned_string);
    371   if (len != size) {
    372     printf("Failed at size %d, length returned %u, align=%p[%d,%d]\n",
    373            size, len, aligned_string, align, or_mask);
    374     return false;
    375   }
    376 
    377   if (verbose) {
    378     printf("Testing size %d with extra zeros after string, align=%p[%d,%d]\n",
    379            size, aligned_string, align, or_mask);
    380   }
    381 
    382   for (size_t j = size+1; j <= size+16; j++) {
    383     aligned_string[j] = '\0';
    384   }
    385 
    386   len = test_strlen(aligned_string);
    387   if (len != size) {
    388     printf("Failed at size %d, length returned %u with zeroes after string, align=%p[%d,%d]\n",
    389            size, len, aligned_string, align, or_mask);
    390     return false;
    391   }
    392 
    393   for (size_t j = size; j <= size+16; j++) {
    394     aligned_string[j] = (char)(32 + (j % 96));
    395   }
    396   return true;
    397 }
    398 
    399 bool runStrlenTest(size_t (*test_strlen)(const char *),
    400                    bool verbose) {
    401   char *string = allocateString();
    402   if (string == NULL) {
    403     perror("Unable to allocate memory.\n");
    404     return false;
    405   }
    406 
    407   // Check different string alignments. All zeroes indicates that the
    408   // unmodified malloc values should be used.
    409   const int aligns[][2] = {
    410     // All zeroes to use the values returned from malloc.
    411     { 0, 0 },
    412 
    413     { 1, 0 },
    414     { 2, 0 },
    415     { 4, 0 },
    416     { 8, 0 },
    417     { 16, 0 },
    418     { 32, 0 },
    419 
    420     { 8, 1 },
    421     { 8, 2 },
    422     { 8, 3 },
    423 
    424     { 4, 1 },
    425     { 4, 2 },
    426     { 4, 3 },
    427   };
    428 
    429   printf("  Verifying string lengths at different alignments.\n");
    430   for (size_t i = 0; i < sizeof(aligns)/sizeof(int[2]); i++) {
    431     for (size_t j = 0; j <= MAX_STRING_TEST_SIZE; j++) {
    432       if (!doStrlenCheck(j, string, aligns[i][0], aligns[i][1], test_strlen, verbose)) {
    433         return false;
    434       }
    435     }
    436   }
    437 
    438   printf("  Verifying strlen does not read past end of string.\n");
    439 
    440   // In order to verify that strlen is not reading past the end of the
    441   // string, create strings that end near unreadable memory.
    442   long pagesize = sysconf(_SC_PAGE_SIZE);
    443   char *memory = (char*)memalign(pagesize, 2 * pagesize);
    444   if (memory == NULL) {
    445     perror("Unable to allocate memory.\n");
    446     return false;
    447   }
    448 
    449   // Make the second page unreadable and unwritable.
    450   if (mprotect(&memory[pagesize], pagesize, PROT_NONE) != 0) {
    451     perror("Unable to set protection of page.\n");
    452     return false;
    453   }
    454 
    455   size_t max_size = pagesize < MAX_STRING_TEST_SIZE ? pagesize-1 : MAX_STRING_TEST_SIZE;
    456   for (long i = 0; i < pagesize; i++) {
    457     memory[i] = (char)(32 + (i % 96));
    458   }
    459 
    460   size_t len;
    461   for (size_t i = 0; i < sizeof(aligns)/sizeof(int[2]); i++) {
    462     for (size_t j = 0; j <= max_size; j++) {
    463       string = &memory[pagesize-j-1];
    464       string[j] = '\0';
    465 
    466       if (verbose) {
    467         printf("Testing size %d overread, align=%p[%d,%d]\n",
    468                j, string, aligns[i][0], aligns[i][1]);
    469       }
    470       len = test_strlen(string);
    471       if (len != j) {
    472         printf("    Failed at size %u, returned %u, align=%p[%d,%d]\n",
    473                j, len, string, aligns[i][0], aligns[i][1]);
    474         return false;
    475       }
    476       string[j] = (char)(32 + (j % 96));
    477     }
    478   }
    479 
    480   printf("  All tests pass.\n");
    481 
    482   return true;
    483 }
    484 
    485 bool runStrcpyTest(char *(*test_strcpy)(char *, const char *),
    486                    bool verbose) {
    487   char *src = allocateString();
    488   if (src == NULL) {
    489     perror("Unable to allocate memory.\n");
    490     return false;
    491   }
    492   char *dst = allocateString();
    493   if (dst == NULL) {
    494     perror("Unable to allocate memory.\n");
    495     return false;
    496   }
    497 
    498   printf("  Verifying string lengths at different alignments.\n");
    499   char *src_align;
    500   char *dst_align;
    501   char *dst_ret;
    502   for (size_t i = 0; i < STRING_ALIGN_LEN; i++) {
    503     for (size_t copy_len = 0; copy_len <= MAX_STRING_TEST_SIZE; copy_len++) {
    504       if (kStringAligns[i][0]) {
    505         src_align = reinterpret_cast<char*>(getAlignedPtr(src+FENCEPOST_LENGTH, kStringAligns[i][0], kStringAligns[i][1]));
    506         dst_align = reinterpret_cast<char*>(getAlignedPtr(dst+FENCEPOST_LENGTH, kStringAligns[i][2], kStringAligns[i][3]));
    507       } else {
    508         src_align = src;
    509         dst_align = dst;
    510       }
    511       setString(src_align, copy_len);
    512       memset(dst_align, 0, copy_len+1);
    513 
    514       if (dst_align != dst) {
    515         setFencepost(reinterpret_cast<uint8_t*>(&dst_align[-FENCEPOST_LENGTH]));
    516       }
    517       setFencepost(reinterpret_cast<uint8_t*>(&dst_align[copy_len+1]));
    518 
    519       if (verbose) {
    520         printf("Testing copy_len %u, src_align=%p[%d,%d], dst_align=%p[%d,%d]\n",
    521                copy_len, src_align, kStringAligns[i][0], kStringAligns[i][1],
    522                dst_align, kStringAligns[i][2], kStringAligns[i][3]);
    523       }
    524 
    525       dst_ret = test_strcpy(dst_align, src_align);
    526       if (dst_ret != dst_align) {
    527         printf("copy_len %u returned incorrect value: expected %p, got %p\n",
    528                copy_len, dst_align, dst_ret);
    529         return false;
    530       }
    531       if (memcmp(src_align, dst_align, copy_len) != 0) {
    532         printf("copy_len %u failed to copy properly: src and dst aren't equal\n", copy_len);
    533         return false;
    534       }
    535 
    536       if (dst_align != dst && !verifyFencepost(reinterpret_cast<uint8_t*>(&dst_align[-FENCEPOST_LENGTH]))) {
    537         printf("copy_len %u fencepost before dst was overwritten\n", copy_len);
    538         return false;
    539       }
    540 
    541       if (!verifyFencepost(reinterpret_cast<uint8_t*>(&dst_align[copy_len+1]))) {
    542         printf("copy_len %u fencepost at end of dst was overwritten\n", copy_len);
    543         return false;
    544       }
    545     }
    546   }
    547 
    548   printf("  All tests pass.\n");
    549 
    550   return true;
    551 }
    552 
    553 bool runStrcatTest(char *(*test_strcat)(char *, const char *),
    554                    bool verbose) {
    555   char *src = allocateString();
    556   if (src == NULL) {
    557     perror("Unable to allocate memory.\n");
    558     return false;
    559   }
    560   char *dst = allocateString();
    561   if (dst == NULL) {
    562     perror("Unable to allocate memory.\n");
    563     return false;
    564   }
    565 
    566   printf("  Verifying string lengths at different alignments.\n");
    567   char *src_align;
    568   char *dst_align;
    569   char *dst_ret;
    570   for (size_t i = 0; i < STRING_ALIGN_LEN; i++) {
    571     for (size_t dst_len = 0; dst_len <= MAX_STRCAT_DST_SIZE; dst_len++) {
    572       for (size_t copy_len = 0; copy_len <= MAX_STRING_TEST_SIZE; copy_len++) {
    573         if (kStringAligns[i][0]) {
    574           src_align = reinterpret_cast<char*>(getAlignedPtr(src+FENCEPOST_LENGTH, kStringAligns[i][0], kStringAligns[i][1]));
    575           dst_align = reinterpret_cast<char*>(getAlignedPtr(dst+FENCEPOST_LENGTH, kStringAligns[i][2], kStringAligns[i][3]));
    576         } else {
    577           src_align = src;
    578           dst_align = dst;
    579         }
    580         setString(src_align, copy_len);
    581         memset(dst_align, 'd', dst_len);
    582         memset(dst_align+dst_len, 0, copy_len+1);
    583 
    584         if (dst_align != dst) {
    585           setFencepost(reinterpret_cast<uint8_t*>(&dst_align[-FENCEPOST_LENGTH]));
    586         }
    587         setFencepost(reinterpret_cast<uint8_t*>(&dst_align[copy_len+dst_len+1]));
    588 
    589         if (verbose) {
    590           printf("Testing copy_len %u, dst_len %u, src_align=%p[%d,%d], dst_align=%p[%d,%d]\n",
    591                  copy_len, dst_len, src_align, kStringAligns[i][0], kStringAligns[i][1],
    592                  dst_align, kStringAligns[i][2], kStringAligns[i][3]);
    593         }
    594 
    595         dst_ret = test_strcat(dst_align, src_align);
    596         if (dst_ret != dst_align) {
    597           printf("dst_len %u, copy_len %u returned incorrect value: expected %p, got %p\n",
    598                 dst_len, copy_len, dst_align, dst_ret);
    599           return false;
    600         }
    601         for (size_t j = 0; j < dst_len; j++) {
    602           if (dst_align[j] != 'd') {
    603             printf("dst_len %u, copy_len %u: strcat overwrote dst string\n",
    604                    dst_len, copy_len);
    605             return false;
    606           }
    607         }
    608         if (memcmp(src_align, dst_align+dst_len, copy_len+1) != 0) {
    609           printf("dst_len %u, copy_len %u failed to copy properly: src and dst aren't equal\n",
    610                  dst_len, copy_len);
    611           return false;
    612         }
    613 
    614         if (dst_align != dst && !verifyFencepost(reinterpret_cast<uint8_t*>(&dst_align[-FENCEPOST_LENGTH]))) {
    615           return false;
    616         }
    617 
    618         if (!verifyFencepost(reinterpret_cast<uint8_t*>(&dst_align[dst_len+copy_len+1]))) {
    619           return false;
    620         }
    621       }
    622     }
    623   }
    624 
    625   printf("  All tests pass.\n");
    626 
    627   return true;
    628 }
    629 
    630 bool runMemcpyTest(void* (*test_memcpy)(void *dst, const void *src, size_t n),
    631                    bool verbose) {
    632   uint8_t *dst = reinterpret_cast<uint8_t*>(malloc(MAX_MEMCPY_BUFFER_SIZE));
    633   uint8_t *src = reinterpret_cast<uint8_t*>(malloc(MAX_MEMCPY_BUFFER_SIZE));
    634   if (dst == NULL || src == NULL) {
    635     perror("Unable to allocate memory.\n");
    636     return false;
    637   }
    638 
    639   // Set the source to a known pattern once. The assumption is that the
    640   // memcpy is not so broken that it will write in to the source buffer.
    641   // However, do not write zeroes into the source so a very quick can be
    642   // made to verify the source has not been modified.
    643   for (int i = 0; i < MAX_MEMCPY_BUFFER_SIZE; i++) {
    644     src[i] = i % 256;
    645     if (src[i] == 0) {
    646       src[i] = 0xaa;
    647     }
    648   }
    649 
    650   const int aligns[][4] = {
    651     // Src and dst use pointers returned by malloc.
    652     { 0, 0, 0, 0 },
    653 
    654     // Src and dst at same alignment.
    655     { 1, 0, 1, 0 },
    656     { 2, 0, 2, 0 },
    657     { 4, 0, 4, 0 },
    658     { 8, 0, 8, 0 },
    659     { 16, 0, 16, 0 },
    660     { 32, 0, 32, 0 },
    661     { 64, 0, 64, 0 },
    662     { 128, 0, 128, 0 },
    663 
    664     // Different alignments between src and dst.
    665     { 8, 0, 4, 0 },
    666     { 4, 0, 8, 0 },
    667     { 16, 0, 4, 0 },
    668     { 4, 0, 16, 0 },
    669 
    670     // General unaligned cases.
    671     { 4, 0, 4, 1 },
    672     { 4, 0, 4, 2 },
    673     { 4, 0, 4, 3 },
    674     { 4, 1, 4, 0 },
    675     { 4, 2, 4, 0 },
    676     { 4, 3, 4, 0 },
    677 
    678     // All non-word aligned cases.
    679     { 4, 1, 4, 0 },
    680     { 4, 1, 4, 1 },
    681     { 4, 1, 4, 2 },
    682     { 4, 1, 4, 3 },
    683 
    684     { 4, 2, 4, 0 },
    685     { 4, 2, 4, 1 },
    686     { 4, 2, 4, 2 },
    687     { 4, 2, 4, 3 },
    688 
    689     { 4, 3, 4, 0 },
    690     { 4, 3, 4, 1 },
    691     { 4, 3, 4, 2 },
    692     { 4, 3, 4, 3 },
    693 
    694     { 2, 0, 4, 0 },
    695     { 4, 0, 2, 0 },
    696     { 2, 0, 2, 0 },
    697 
    698     // Invoke the unaligned case where the code needs to align dst to 0x10.
    699     { 128, 1, 128, 4 },
    700     { 128, 1, 128, 8 },
    701     { 128, 1, 128, 12 },
    702     { 128, 1, 128, 16 },
    703   };
    704 
    705   printf("  Verifying variable sized copies at different alignments.\n");
    706   uint8_t *src_align, *dst_align;
    707   for (size_t i = 0; i < sizeof(aligns)/sizeof(int[4]); i++) {
    708     for (size_t len = 0; len <= MAX_MEMCPY_TEST_SIZE; len++) {
    709       if (aligns[i][0]) {
    710         src_align = (uint8_t*)getAlignedPtr(src+FENCEPOST_LENGTH, aligns[i][0],
    711                                             aligns[i][1]);
    712         dst_align = (uint8_t*)getAlignedPtr(dst+FENCEPOST_LENGTH, aligns[i][2],
    713                                             aligns[i][3]);
    714       } else {
    715         src_align = src;
    716         dst_align = dst;
    717       }
    718 
    719       if (verbose) {
    720         printf("Testing size %d, src_align=%p[%d,%d], dst_align=%p[%d,%d]\n",
    721                len, src_align, aligns[i][0], aligns[i][1],
    722                dst_align, aligns[i][2], aligns[i][3]);
    723       }
    724 
    725       memset(dst_align, 0, len);
    726 
    727       // Don't add a pre fencepost if we are using the value from the malloc.
    728       if (dst_align != dst) {
    729         setFencepost(&dst_align[-8]);
    730       }
    731       setFencepost(&dst_align[len]);
    732 
    733       test_memcpy(dst_align, src_align, len);
    734 
    735       for (size_t j = 0; j < len; j++) {
    736         if (dst_align[j] != src_align[j] || !src_align[j]) {
    737           if (!src_align[j]) {
    738             printf("    src_align[%d] is 0, memcpy wrote into the source.\n", j);
    739           } else {
    740             printf("    mismatch at %d, expected %d found %d\n", j,
    741                    src_align[j], dst_align[j]);
    742           }
    743           printf("    Failed at size %d, src_align=%p[%d,%d], dst_align=%p[%d,%d]\n",
    744                  len, src_align, aligns[i][0], aligns[i][1],
    745                  dst_align, aligns[i][2], aligns[i][3]);
    746           return false;
    747         }
    748       }
    749       if (dst_align != dst && !verifyFencepost(&dst_align[-8])) {
    750         printf("    wrote before the array.\n");
    751         printf("    Failed at size %d, src_align=%p[%d,%d], dst_align=%p[%d,%d]\n",
    752                len, src_align, aligns[i][0], aligns[i][1],
    753                dst_align, aligns[i][2], aligns[i][3]);
    754         return false;
    755       }
    756       if (!verifyFencepost(&dst_align[len])) {
    757         printf("    wrote past the end of the array.\n");
    758         printf("    Failed at size %d, src_align=%p[%d,%d], dst_align=%p[%d,%d]\n",
    759                len, src_align, aligns[i][0], aligns[i][1],
    760                dst_align, aligns[i][2], aligns[i][3]);
    761         return false;
    762       }
    763     }
    764   }
    765 
    766   printf("  All tests pass.\n");
    767 
    768   return true;
    769 }
    770 
    771 bool runMemsetTest(void* (*test_memset)(void *s, int c, size_t n),
    772                    bool verbose) {
    773   uint8_t *buf = reinterpret_cast<uint8_t*>(malloc(MAX_MEMSET_BUFFER_SIZE));
    774   if (buf == NULL) {
    775     perror("Unable to allocate memory.\n");
    776     return false;
    777   }
    778 
    779   const int aligns[][2] = {
    780     // Use malloc return values unaltered.
    781     { 0, 0 },
    782 
    783     // Different alignments.
    784     { 1, 0 },
    785     { 2, 0 },
    786     { 4, 0 },
    787     { 8, 0 },
    788     { 16, 0 },
    789     { 32, 0 },
    790     { 64, 0 },
    791 
    792     // Different alignments between src and dst.
    793     { 8, 1 },
    794     { 8, 2 },
    795     { 8, 3 },
    796     { 8, 4 },
    797     { 8, 5 },
    798     { 8, 6 },
    799     { 8, 7 },
    800   };
    801 
    802   printf("  Verifying variable sized memsets at different alignments.\n");
    803   uint8_t *buf_align;
    804   for (size_t i = 0; i < sizeof(aligns)/sizeof(int[2]); i++) {
    805     for (size_t len = 0; len <= MAX_MEMSET_TEST_SIZE; len++) {
    806       if (aligns[i]) {
    807         buf_align = (uint8_t*)getAlignedPtr(buf+FENCEPOST_LENGTH, aligns[i][0],
    808                                             aligns[i][1]);
    809       } else {
    810         buf_align = buf;
    811       }
    812 
    813       if (verbose) {
    814         printf("Testing size %d, buf_align=%p[%d,%d]\n",
    815                len, buf_align, aligns[i][0], aligns[i][1]);
    816       }
    817 
    818       // Set the buffer to all zero without memset since it might be the
    819       // function we are testing.
    820       for (size_t j = 0; j < len; j++) {
    821         buf_align[j] = 0;
    822       }
    823 
    824       // Don't add a pre fencepost if we are using the value from the malloc.
    825       if (buf_align != buf) {
    826         setFencepost(&buf_align[-8]);
    827       }
    828       setFencepost(&buf_align[len]);
    829 
    830       int value = (len % 255) + 1;
    831       test_memset(buf_align, value, len);
    832 
    833       for (size_t j = 0; j < len; j++) {
    834         if (buf_align[j] != value) {
    835           printf("    Failed at size %d[%d,%d!=%d], buf_align=%p[%d,%d]\n",
    836                  len, j, buf_align[j], value, buf_align, aligns[i][0],
    837                  aligns[i][1]);
    838           return false;
    839         }
    840       }
    841       if (buf_align != buf && !verifyFencepost(&buf_align[-8])) {
    842         printf("    wrote before the beginning of the array.\n");
    843         printf("    Failed at size %d, buf_align=%p[%d,%d]\n",
    844                len, buf_align, aligns[i][0], aligns[i][1]);
    845         return false;
    846       }
    847       if (!verifyFencepost(&buf_align[len])) {
    848         printf("    wrote after the end of the array.\n");
    849         printf("    Failed at size %d, buf_align=%p[%d,%d]\n",
    850                len, buf_align, aligns[i][0], aligns[i][1]);
    851         return false;
    852       }
    853     }
    854   }
    855 
    856   printf("  All tests pass.\n");
    857 
    858   return true;
    859 }
    860 
    861 int main(int argc, char **argv) {
    862   bool verbose = false;
    863   if (argc == 2 && strcmp(argv[1], "-v") == 0) {
    864     verbose = true;
    865   }
    866 
    867   bool tests_passing = true;
    868 
    869   printf("Testing strcmp...\n");
    870   tests_passing = runStrcmpTest(strcmp, verbose) && tests_passing;
    871 
    872   printf("Testing memcpy...\n");
    873   tests_passing = runMemcpyTest(memcpy, verbose) && tests_passing;
    874 
    875   printf("Testing memset...\n");
    876   tests_passing = runMemsetTest(memset, verbose) && tests_passing;
    877 
    878   printf("Testing strlen...\n");
    879   tests_passing = runStrlenTest(strlen, verbose) && tests_passing;
    880 
    881   printf("Testing strcpy...\n");
    882   tests_passing = runStrcpyTest(strcpy, verbose) && tests_passing;
    883 
    884   printf("Testing strcat...\n");
    885   tests_passing = runStrcatTest(strcat, verbose) && tests_passing;
    886 
    887   return (tests_passing ? 0 : 1);
    888 }
    889