main.cpp revision a63c049f23c49b6345bf2c845a415109c5471ebe
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.
23extern "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_STRCMP_TEST_SIZE      1024
35#define MAX_STRCMP_BUFFER_SIZE    (3 * MAX_STRCMP_TEST_SIZE)
36
37#define MAX_STRLEN_TEST_SIZE      1024
38#define MAX_STRLEN_BUFFER_SIZE    (3 * MAX_STRLEN_TEST_SIZE)
39
40// Return a pointer into the current string with the specified alignment.
41void *getAlignedPtr(void *orig_ptr, int alignment, int or_mask) {
42  uint64_t ptr = reinterpret_cast<uint64_t>(orig_ptr);
43  if (alignment > 0) {
44      // When setting the alignment, set it to exactly the alignment chosen.
45      // The pointer returned will be guaranteed not to be aligned to anything
46      // more than that.
47      ptr += alignment - (ptr & (alignment - 1));
48      ptr |= alignment | or_mask;
49  }
50
51  return reinterpret_cast<void*>(ptr);
52}
53
54void setFencepost(uint8_t *buffer) {
55  for (int i = 0; i < FENCEPOST_LENGTH; i += 2) {
56    buffer[i] = 0xde;
57    buffer[i+1] = 0xad;
58  }
59}
60
61bool verifyFencepost(uint8_t *buffer) {
62  for (int i = 0; i < FENCEPOST_LENGTH; i += 2) {
63    if (buffer[i] != 0xde || buffer[i+1] != 0xad) {
64      uint8_t expected_value;
65      if (buffer[i] == 0xde) {
66        i++;
67        expected_value = 0xad;
68      } else {
69        expected_value = 0xde;
70      }
71      printf("   mismatch at fencepost[%d], expected %d found %d\n",
72             i, expected_value, buffer[i]);
73      return false;
74    }
75  }
76  return true;
77}
78
79bool doStrcmpExpectEqual(char *string1, char *string2, int align[4],
80                         int (*test_strcmp)(const char *s1, const char *s2),
81                         bool verbose) {
82  char *align_str1 = (char*)getAlignedPtr(string1, align[0], align[1]);
83  char *align_str2 = (char*)getAlignedPtr(string2, align[2], align[3]);
84
85  for (size_t i = 0; i < MAX_STRCMP_TEST_SIZE; i++) {
86    for (size_t j = 0; j < i; j++) {
87      align_str1[j] = (char)(32 + (j % 96));
88      align_str2[j] = align_str1[j];
89    }
90    align_str1[i] = '\0';
91    align_str2[i] = '\0';
92
93    // Set the characters after the string terminates to different values
94    // to verify that the strcmp is not over checking.
95    for (size_t j = i+1; j < i+64; j++) {
96      align_str1[j] = (char)(32 + j);
97      align_str2[j] = (char)(40 + j);
98    }
99
100    if (verbose) {
101      printf("Testing size %d, align_str1=%p[%d,%d], align_str2=%p[%d,%d]\n",
102             i, align_str1, align[0], align[1], align_str2, align[2], align[3]);
103    }
104
105    if (test_strcmp(align_str1, align_str2) != 0) {
106      printf("    Failed at size %d, src1 %p, src2 %p\n",
107             i, align_str1, align_str2);
108      return false;
109    }
110  }
111
112  return true;
113}
114
115bool doStrcmpExpectDiff(char *string1, char *string2, int diff_align[2],
116                        int align[4], char diff_char,
117                        int (*test_strcmp)(const char *s1, const char *s2),
118                        bool verbose) {
119  char *align_str1 = (char*)getAlignedPtr(string1, align[0], align[1]);
120  char *align_str2 = (char*)getAlignedPtr(string2, align[2], align[3]);
121
122  for (int i = 0; i < MAX_STRCMP_TEST_SIZE; i++) {
123    // Use valid ascii characters, no unprintables characters.
124    align_str1[i] = (char)(32 + (i % 96));
125    if (align_str1[i] == diff_char) {
126      // Assumes that one less than the diff character is still a valid
127      // character.
128      align_str1[i] = diff_char-1;
129    }
130    align_str2[i] = align_str1[i];
131  }
132  align_str1[MAX_STRCMP_TEST_SIZE] = '\0';
133  align_str2[MAX_STRCMP_TEST_SIZE] = '\0';
134
135  // Quick check to make sure that the strcmp knows that everything is
136  // equal. If it's so broken that it already thinks the strings are
137  // different, then there is no point running any of the other tests.
138  if (test_strcmp(align_str1, align_str2) != 0) {
139    printf("    strcmp is too broken to do difference testing.\n");
140    return false;
141  }
142
143  // Get a pointer into the string at the specified alignment.
144  char *bad = (char*)getAlignedPtr(align_str1+MAX_STRCMP_TEST_SIZE/2,
145                                   diff_align[0], diff_align[1]);
146
147  char saved_char = bad[0];
148  bad[0] = diff_char;
149
150  if (verbose) {
151    printf("Testing difference, align_str1=%p[%d,%d], align_str2=%p[%d,%d]\n",
152           align_str1, align[0], align[1], align_str2, align[2], align[3]);
153  }
154  if (test_strcmp(align_str1, align_str2) == 0) {
155    printf("   Did not miscompare at size %d, src1 %p, src2 %p, diff %p\n",
156           MAX_STRCMP_TEST_SIZE, align_str1, align_str2, bad);
157    return false;
158  }
159  bad[0] = saved_char;
160
161  // Re-verify that something hasn't gone horribly wrong.
162  if (test_strcmp(align_str1, align_str2) != 0) {
163    printf("   strcmp is too broken to do difference testing.\n");
164    return false;
165  }
166
167  bad = (char*)getAlignedPtr(align_str2+MAX_STRCMP_TEST_SIZE/2, diff_align[0],
168                             diff_align[1]);
169  bad[0] = diff_char;
170
171  if (verbose) {
172    printf("Testing reverse difference, align_str1=%p[%d,%d], align_str2=%p[%d,%d]\n",
173           align_str1, align[0], align[1], align_str2, align[2], align[3]);
174  }
175  if (test_strcmp(align_str1, align_str2) == 0) {
176    printf("    Did not miscompare at size %d, src1 %p, src2 %p, diff %p\n",
177           MAX_STRCMP_TEST_SIZE, align_str1, align_str2, bad);
178    return false;
179  }
180
181  return true;
182}
183
184bool doStrcmpCheckRead(int (*test_strcmp)(const char *s1, const char *s2),
185                       bool verbose) {
186  // In order to verify that the strcmp is not reading past the end of the
187  // string, create some strings that end near unreadable memory.
188  long pagesize = sysconf(_SC_PAGE_SIZE);
189  char *memory = (char*)memalign(pagesize, 2 * pagesize);
190  if (memory == NULL) {
191    perror("Unable to allocate memory.\n");
192    return false;
193  }
194
195  // Make the second page unreadable and unwritable.
196  if (mprotect(&memory[pagesize], pagesize, PROT_NONE) != 0) {
197    perror("Unable to set protection of page.\n");
198    return false;
199  }
200
201  size_t max_size = pagesize < MAX_STRCMP_TEST_SIZE ? pagesize-1 : MAX_STRCMP_TEST_SIZE;
202  // Allocate an extra byte beyond the string terminator to allow us to
203  // extend the string to be larger than our protected string.
204  char *other_string = (char *)malloc(max_size+2);
205  if (other_string == NULL) {
206    perror("Unable to allocate memory.\n");
207    return false;
208  }
209  char *string;
210  for (size_t i = 0; i <= max_size; i++) {
211    string = &memory[pagesize-i-1];
212    for (size_t j = 0; j < i; j++) {
213      other_string[j] = (char)(32 + (j % 96));
214      string[j] = other_string[j];
215    }
216    other_string[i] = '\0';
217    string[i] = '\0';
218
219    if (verbose) {
220      printf("Testing size %d, strings equal.\n", i);
221    }
222    if (test_strcmp(other_string, string) != 0) {
223      printf("    Failed at size %d, src1 %p, src2 %p\n", i, other_string, string);
224      return false;
225    }
226
227    if (verbose) {
228      printf("Testing size %d, strings equal reverse strings.\n", i);
229    }
230    if (test_strcmp(string, other_string) != 0) {
231      printf("    Failed at size %d, src1 %p, src2 %p\n", i, string, other_string);
232      return false;
233    }
234
235    // Now make other_string longer than our protected string.
236    other_string[i] = '1';
237    other_string[i+1] = '\0';
238
239    if (verbose) {
240      printf("Testing size %d, strings not equal.\n", i);
241    }
242    if (test_strcmp(other_string, string) == 0) {
243      printf("    Failed at size %d, src1 %p, src2 %p\n", i, other_string, string);
244      return false;
245    }
246
247    if (verbose) {
248      printf("Testing size %d, strings not equal reverse the strings.\n", i);
249    }
250    if (test_strcmp(string, other_string) == 0) {
251      printf("    Failed at size %d, src1 %p, src2 %p\n", i, string, other_string);
252      return false;
253    }
254  }
255  return true;
256}
257
258bool runStrcmpTest(int (*test_strcmp)(const char *s1, const char *s2),
259                   bool verbose) {
260  // Allocate two large buffers to hold the two strings.
261  char *string1 = reinterpret_cast<char*>(malloc(MAX_STRCMP_BUFFER_SIZE+1));
262  char *string2 = reinterpret_cast<char*>(malloc(MAX_STRCMP_BUFFER_SIZE+1));
263  if (string1 == NULL || string2 == NULL) {
264    perror("Unable to allocate memory.\n");
265    return false;
266  }
267
268  // Initialize the strings to be exactly the same.
269  for (int i = 0; i < MAX_STRCMP_BUFFER_SIZE; i++) {
270    string1[i] = (char)(32 + (i % 96));
271    string2[i] = string1[i];
272  }
273  string1[MAX_STRCMP_BUFFER_SIZE] = '\0';
274  string2[MAX_STRCMP_BUFFER_SIZE] = '\0';
275
276  // Check different string alignments. All zeroes indicates that the
277  // unmodified malloc values should be used.
278  int string_aligns[][4] = {
279    // All zeroes to use the values returned from malloc.
280    { 0, 0, 0, 0 },
281
282    { 1, 0, 1, 0 },
283    { 2, 0, 2, 0 },
284    { 4, 0, 4, 0 },
285    { 8, 0, 8, 0 },
286
287    { 8, 0, 4, 0 },
288    { 4, 0, 8, 0 },
289
290    { 8, 0, 8, 1 },
291    { 8, 0, 8, 2 },
292    { 8, 0, 8, 3 },
293    { 8, 1, 8, 0 },
294    { 8, 2, 8, 0 },
295    { 8, 3, 8, 0 },
296
297    { 4, 0, 4, 1 },
298    { 4, 0, 4, 2 },
299    { 4, 0, 4, 3 },
300    { 4, 1, 4, 0 },
301    { 4, 2, 4, 0 },
302    { 4, 3, 4, 0 },
303  };
304
305  printf("  Verifying equal sized strings at different alignments.\n");
306  for (size_t i = 0; i < sizeof(string_aligns)/sizeof(int[4]); i++) {
307    if (!doStrcmpExpectEqual(string1, string2, string_aligns[i], test_strcmp,
308                             verbose)) {
309      return false;
310    }
311  }
312
313  // Test the function finds strings with differences at specific locations.
314  int diff_aligns[][2] = {
315    { 4, 0 },
316    { 4, 1 },
317    { 4, 2 },
318    { 4, 3 },
319    { 8, 0 },
320    { 8, 1 },
321    { 8, 2 },
322    { 8, 3 },
323  };
324  printf("  Verifying different strings at different alignments.\n");
325  for (size_t i = 0; i < sizeof(diff_aligns)/sizeof(int[2]); i++) {
326    // First loop put the string terminator at the chosen alignment.
327    for (size_t j = 0; j < sizeof(string_aligns)/sizeof(int[4]); j++) {
328      if (!doStrcmpExpectDiff(string1, string2, diff_aligns[i],
329                              string_aligns[j], '\0', test_strcmp, verbose)) {
330        return false;
331      }
332    }
333    // Second loop put a different character at the chosen alignment.
334    // This character is guaranteed not to be in the original string.
335    for (size_t j = 0; j < sizeof(string_aligns)/sizeof(int[4]); j++) {
336      if (!doStrcmpExpectDiff(string1, string2, diff_aligns[i],
337                              string_aligns[j], '\0', test_strcmp, verbose)) {
338        return false;
339      }
340    }
341  }
342
343  printf("  Verifying strcmp does not read too many bytes.\n");
344  if (!doStrcmpCheckRead(test_strcmp, verbose)) {
345    return false;
346  }
347
348  printf("  All tests pass.\n");
349
350  return true;
351}
352
353bool doStrlenCheck(size_t size, char *string, int align, int or_mask,
354                   size_t (*test_strlen)(const char *), bool verbose) {
355  char *aligned_string = reinterpret_cast<char*>(getAlignedPtr(string, align, or_mask));
356  size_t len;
357  if (verbose) {
358    printf("Testing size %d, align=%p[%d,%d]\n", size, aligned_string, align, or_mask);
359  }
360
361  aligned_string[size] = '\0';
362  len = test_strlen(aligned_string);
363  if (len != size) {
364    printf("Failed at size %d, length returned %u, align=%p[%d,%d]\n",
365           size, len, aligned_string, align, or_mask);
366    return false;
367  }
368
369  if (verbose) {
370    printf("Testing size %d with extra zeros after string, align=%p[%d,%d]\n",
371           size, aligned_string, align, or_mask);
372  }
373
374  for (size_t j = size+1; j <= size+16; j++) {
375    aligned_string[j] = '\0';
376  }
377
378  len = test_strlen(aligned_string);
379  if (len != size) {
380    printf("Failed at size %d, length returned %u with zeroes after string, align=%p[%d,%d]\n",
381           size, len, aligned_string, align, or_mask);
382    return false;
383  }
384
385  for (size_t j = size; j <= size+16; j++) {
386    aligned_string[j] = (char)(32 + (j % 96));
387  }
388  return true;
389}
390
391bool runStrlenTest(size_t (*test_strlen)(const char *),
392                   bool verbose) {
393  // Allocate two large buffers to hold the two strings.
394  char *string = reinterpret_cast<char*>(malloc(MAX_STRLEN_BUFFER_SIZE+1));
395  if (string == NULL) {
396    perror("Unable to allocate memory.\n");
397    return false;
398  }
399
400  // Initialize the strings to be exactly the same.
401  for (int i = 0; i < MAX_STRLEN_BUFFER_SIZE; i++) {
402    string[i] = (char)(32 + (i % 96));
403  }
404  string[MAX_STRLEN_BUFFER_SIZE] = '\0';
405
406  // Check different string alignments. All zeroes indicates that the
407  // unmodified malloc values should be used.
408  int aligns[][2] = {
409    // All zeroes to use the values returned from malloc.
410    { 0, 0 },
411
412    { 1, 0 },
413    { 2, 0 },
414    { 4, 0 },
415    { 8, 0 },
416    { 16, 0 },
417    { 32, 0 },
418
419    { 8, 1 },
420    { 8, 2 },
421    { 8, 3 },
422
423    { 4, 1 },
424    { 4, 2 },
425    { 4, 3 },
426  };
427
428  printf("  Verifying string lengths at different alignments.\n");
429  for (size_t i = 0; i < sizeof(aligns)/sizeof(int[2]); i++) {
430    for (size_t j = 0; j <= MAX_STRLEN_TEST_SIZE; j++) {
431      if (!doStrlenCheck(j, string, aligns[i][0], aligns[i][1], test_strlen, verbose)) {
432        return false;
433      }
434    }
435  }
436
437  printf("  Verifying strlen does not read past end of string.\n");
438
439  // In order to verify that strlen is not reading past the end of the
440  // string, create strings that end near unreadable memory.
441  long pagesize = sysconf(_SC_PAGE_SIZE);
442  char *memory = (char*)memalign(pagesize, 2 * pagesize);
443  if (memory == NULL) {
444    perror("Unable to allocate memory.\n");
445    return false;
446  }
447
448  // Make the second page unreadable and unwritable.
449  if (mprotect(&memory[pagesize], pagesize, PROT_NONE) != 0) {
450    perror("Unable to set protection of page.\n");
451    return false;
452  }
453
454  size_t max_size = pagesize < MAX_STRLEN_TEST_SIZE ? pagesize-1 : MAX_STRLEN_TEST_SIZE;
455  for (long i = 0; i < pagesize; i++) {
456    memory[i] = (char)(32 + (i % 96));
457  }
458
459  size_t len;
460  for (size_t i = 0; i < sizeof(aligns)/sizeof(int[2]); i++) {
461    for (size_t j = 0; j <= max_size; j++) {
462      string = &memory[pagesize-j-1];
463      string[j] = '\0';
464
465      if (verbose) {
466        printf("Testing size %d overread, align=%p[%d,%d]\n",
467               j, string, aligns[i][0], aligns[i][1]);
468      }
469      len = test_strlen(string);
470      if (len != j) {
471        printf("    Failed at size %u, returned %u, align=%p[%d,%d]\n",
472               j, len, string, aligns[i][0], aligns[i][1]);
473        return false;
474      }
475      string[j] = (char)(32 + (j % 96));
476    }
477  }
478
479  printf("  All tests pass.\n");
480
481  return true;
482}
483
484bool runMemcpyTest(void* (*test_memcpy)(void *dst, const void *src, size_t n),
485                   bool verbose) {
486  // Allocate two large buffers to hold the dst and src.
487  uint8_t *dst = reinterpret_cast<uint8_t*>(malloc(MAX_MEMCPY_BUFFER_SIZE));
488  uint8_t *src = reinterpret_cast<uint8_t*>(malloc(MAX_MEMCPY_BUFFER_SIZE));
489  if (dst == NULL || src == NULL) {
490    perror("Unable to allocate memory.\n");
491    return false;
492  }
493
494  // Set the source to a known pattern once. The assumption is that the
495  // memcpy is not so broken that it will write in to the source buffer.
496  // However, do not write zeroes into the source so a very quick can be
497  // made to verify the source has not been modified.
498  for (int i = 0; i < MAX_MEMCPY_BUFFER_SIZE; i++) {
499    src[i] = i % 256;
500    if (src[i] == 0) {
501      src[i] = 0xaa;
502    }
503  }
504
505  int aligns[][4] = {
506    // Src and dst use pointers returned by malloc.
507    { 0, 0, 0, 0 },
508
509    // Src and dst at same alignment.
510    { 1, 0, 1, 0 },
511    { 2, 0, 2, 0 },
512    { 4, 0, 4, 0 },
513    { 8, 0, 8, 0 },
514    { 16, 0, 16, 0 },
515    { 32, 0, 32, 0 },
516    { 64, 0, 64, 0 },
517    { 128, 0, 128, 0 },
518
519    // Different alignments between src and dst.
520    { 8, 0, 4, 0 },
521    { 4, 0, 8, 0 },
522    { 16, 0, 4, 0 },
523    { 4, 0, 16, 0 },
524
525    // General unaligned cases.
526    { 4, 0, 4, 1 },
527    { 4, 0, 4, 2 },
528    { 4, 0, 4, 3 },
529    { 4, 1, 4, 0 },
530    { 4, 2, 4, 0 },
531    { 4, 3, 4, 0 },
532
533    // All non-word aligned cases.
534    { 4, 1, 4, 0 },
535    { 4, 1, 4, 1 },
536    { 4, 1, 4, 2 },
537    { 4, 1, 4, 3 },
538
539    { 4, 2, 4, 0 },
540    { 4, 2, 4, 1 },
541    { 4, 2, 4, 2 },
542    { 4, 2, 4, 3 },
543
544    { 4, 3, 4, 0 },
545    { 4, 3, 4, 1 },
546    { 4, 3, 4, 2 },
547    { 4, 3, 4, 3 },
548
549    { 2, 0, 4, 0 },
550    { 4, 0, 2, 0 },
551    { 2, 0, 2, 0 },
552
553    // Invoke the unaligned case where the code needs to align dst to 0x10.
554    { 128, 1, 128, 4 },
555    { 128, 1, 128, 8 },
556    { 128, 1, 128, 12 },
557    { 128, 1, 128, 16 },
558  };
559
560  printf("  Verifying variable sized copies at different alignments.\n");
561  uint8_t *src_align, *dst_align;
562  for (size_t i = 0; i < sizeof(aligns)/sizeof(int[4]); i++) {
563    for (size_t len = 0; len <= MAX_MEMCPY_TEST_SIZE; len++) {
564      if (aligns[i][0]) {
565        src_align = (uint8_t*)getAlignedPtr(src+FENCEPOST_LENGTH, aligns[i][0],
566                                            aligns[i][1]);
567        dst_align = (uint8_t*)getAlignedPtr(dst+FENCEPOST_LENGTH, aligns[i][2],
568                                            aligns[i][3]);
569      } else {
570        src_align = src;
571        dst_align = dst;
572      }
573
574      if (verbose) {
575        printf("Testing size %d, src_align=%p[%d,%d], dst_align=%p[%d,%d]\n",
576               len, src_align, aligns[i][0], aligns[i][1],
577               dst_align, aligns[i][2], aligns[i][3]);
578      }
579
580      memset(dst_align, 0, len);
581
582      // Don't add a pre fencepost if we are using the value from the malloc.
583      if (dst_align != dst) {
584        setFencepost(&dst_align[-8]);
585      }
586      setFencepost(&dst_align[len]);
587
588      test_memcpy(dst_align, src_align, len);
589
590      for (size_t j = 0; j < len; j++) {
591        if (dst_align[j] != src_align[j] || !src_align[j]) {
592          if (!src_align[j]) {
593            printf("    src_align[%d] is 0, memcpy wrote into the source.\n", j);
594          } else {
595            printf("    mismatch at %d, expected %d found %d\n", j,
596                   src_align[j], dst_align[j]);
597          }
598          printf("    Failed at size %d, src_align=%p[%d,%d], dst_align=%p[%d,%d]\n",
599                 len, src_align, aligns[i][0], aligns[i][1],
600                 dst_align, aligns[i][2], aligns[i][3]);
601          return false;
602        }
603      }
604      if (dst_align != dst && !verifyFencepost(&dst_align[-8])) {
605        printf("    wrote before the array.\n");
606        printf("    Failed at size %d, src_align=%p[%d,%d], dst_align=%p[%d,%d]\n",
607               len, src_align, aligns[i][0], aligns[i][1],
608               dst_align, aligns[i][2], aligns[i][3]);
609        return false;
610      }
611      if (!verifyFencepost(&dst_align[len])) {
612        printf("    wrote past the end of the array.\n");
613        printf("    Failed at size %d, src_align=%p[%d,%d], dst_align=%p[%d,%d]\n",
614               len, src_align, aligns[i][0], aligns[i][1],
615               dst_align, aligns[i][2], aligns[i][3]);
616        return false;
617      }
618    }
619  }
620
621  printf("  All tests pass.\n");
622
623  return true;
624}
625
626bool runMemsetTest(void* (*test_memset)(void *s, int c, size_t n),
627                   bool verbose) {
628  // Allocate one large buffer to hold the dst.
629  uint8_t *buf = reinterpret_cast<uint8_t*>(malloc(MAX_MEMSET_BUFFER_SIZE));
630  if (buf == NULL) {
631    perror("Unable to allocate memory.\n");
632    return false;
633  }
634
635  int aligns[][2] = {
636    // Use malloc return values unaltered.
637    { 0, 0 },
638
639    // Different alignments.
640    { 1, 0 },
641    { 2, 0 },
642    { 4, 0 },
643    { 8, 0 },
644    { 16, 0 },
645    { 32, 0 },
646    { 64, 0 },
647
648    // Different alignments between src and dst.
649    { 8, 1 },
650    { 8, 2 },
651    { 8, 3 },
652    { 8, 4 },
653    { 8, 5 },
654    { 8, 6 },
655    { 8, 7 },
656  };
657
658  printf("  Verifying variable sized memsets at different alignments.\n");
659  uint8_t *buf_align;
660  for (size_t i = 0; i < sizeof(aligns)/sizeof(int[2]); i++) {
661    for (size_t len = 0; len <= MAX_MEMSET_TEST_SIZE; len++) {
662      if (aligns[i]) {
663        buf_align = (uint8_t*)getAlignedPtr(buf+FENCEPOST_LENGTH, aligns[i][0],
664                                            aligns[i][1]);
665      } else {
666        buf_align = buf;
667      }
668
669      if (verbose) {
670        printf("Testing size %d, buf_align=%p[%d,%d]\n",
671               len, buf_align, aligns[i][0], aligns[i][1]);
672      }
673
674      // Set the buffer to all zero without memset since it might be the
675      // function we are testing.
676      for (size_t j = 0; j < len; j++) {
677        buf_align[j] = 0;
678      }
679
680      // Don't add a pre fencepost if we are using the value from the malloc.
681      if (buf_align != buf) {
682        setFencepost(&buf_align[-8]);
683      }
684      setFencepost(&buf_align[len]);
685
686      int value = (len % 255) + 1;
687      test_memset(buf_align, value, len);
688
689      for (size_t j = 0; j < len; j++) {
690        if (buf_align[j] != value) {
691          printf("    Failed at size %d[%d,%d!=%d], buf_align=%p[%d,%d]\n",
692                 len, j, buf_align[j], value, buf_align, aligns[i][0],
693                 aligns[i][1]);
694          return false;
695        }
696      }
697      if (buf_align != buf && !verifyFencepost(&buf_align[-8])) {
698        printf("    wrote before the beginning of the array.\n");
699        printf("    Failed at size %d, buf_align=%p[%d,%d]\n",
700               len, buf_align, aligns[i][0], aligns[i][1]);
701        return false;
702      }
703      if (!verifyFencepost(&buf_align[len])) {
704        printf("    wrote after the end of the array.\n");
705        printf("    Failed at size %d, buf_align=%p[%d,%d]\n",
706               len, buf_align, aligns[i][0], aligns[i][1]);
707        return false;
708      }
709    }
710  }
711
712  printf("  All tests pass.\n");
713
714  return true;
715}
716
717int main(int argc, char **argv) {
718  bool verbose = false;
719  if (argc == 2 && strcmp(argv[1], "-v") == 0) {
720    verbose = true;
721  }
722
723  bool tests_passing = true;
724
725  printf("Testing strcmp...\n");
726  tests_passing = runStrcmpTest(strcmp, verbose) && tests_passing;
727
728  printf("Testing memcpy...\n");
729  tests_passing = runMemcpyTest(memcpy, verbose) && tests_passing;
730
731  printf("Testing memset...\n");
732  tests_passing = runMemsetTest(memset, verbose) && tests_passing;
733
734  printf("Testing strlen...\n");
735  tests_passing = runStrlenTest(strlen, verbose) && tests_passing;
736
737  return (tests_passing ? 0 : 1);
738}
739