main.cpp revision 1685d00d0a6b905a820a76c9686b6b4b077dfe4a
1fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris/*
2fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris** Copyright 2013 The Android Open Source Project
3fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris**
4fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris** Licensed under the Apache License, Version 2.0 (the "License");
5fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris** you may not use this file except in compliance with the License.
6fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris** You may obtain a copy of the License at
7fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris**
8fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris**     http://www.apache.org/licenses/LICENSE-2.0
9fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris**
10fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris** Unless required by applicable law or agreed to in writing, software
11fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris** distributed under the License is distributed on an "AS IS" BASIS,
12fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris** See the License for the specific language governing permissions and
14fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris** limitations under the License.
15fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris*/
16fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
17fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris#include <stdio.h>
18fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris#include <stdlib.h>
19fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris#include <unistd.h>
20fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris#include <sys/mman.h>
21fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
22fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris// Put any local test functions into the extern below.
23fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferrisextern "C" {
24fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris}
25fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
26f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris#define FENCEPOST_LENGTH          8
27f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris
28fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris#define MAX_MEMCPY_TEST_SIZE      2048
29fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris#define MAX_MEMCPY_BUFFER_SIZE    (3 * MAX_MEMCPY_TEST_SIZE)
30fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
31cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris#define MAX_MEMSET_TEST_SIZE      2048
32cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris#define MAX_MEMSET_BUFFER_SIZE    (3 * MAX_MEMSET_TEST_SIZE)
33cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris
34fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris#define MAX_STRCMP_TEST_SIZE      1024
35fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris#define MAX_STRCMP_BUFFER_SIZE    (3 * MAX_STRCMP_TEST_SIZE)
36fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
37fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris// Return a pointer into the current string with the specified alignment.
38fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferrisvoid *getAlignedPtr(void *orig_ptr, int alignment, int or_mask) {
39fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  uint64_t ptr = reinterpret_cast<uint64_t>(orig_ptr);
40fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  if (alignment > 0) {
41fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      // When setting the alignment, set it to exactly the alignment chosen.
42fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      // The pointer returned will be guaranteed not to be aligned to anything
43fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      // more than that.
44fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      ptr += alignment - (ptr & (alignment - 1));
45fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      ptr |= alignment | or_mask;
46fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  }
47fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
48fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  return reinterpret_cast<void*>(ptr);
49fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris}
50fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
51f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferrisvoid setFencepost(uint8_t *buffer) {
52f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  for (int i = 0; i < FENCEPOST_LENGTH; i += 2) {
53f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    buffer[i] = 0xde;
54f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    buffer[i+1] = 0xad;
55f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  }
56f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris}
57f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris
58f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferrisbool verifyFencepost(uint8_t *buffer) {
59f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  for (int i = 0; i < FENCEPOST_LENGTH; i += 2) {
60f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    if (buffer[i] != 0xde || buffer[i+1] != 0xad) {
61f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      uint8_t expected_value;
62f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      if (buffer[i] == 0xde) {
63f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        i++;
64f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        expected_value = 0xad;
65f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      } else {
66f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        expected_value = 0xde;
67f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      }
68f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      printf("   mismatch at fencepost[%d], expected %d found %d\n",
69f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris             i, expected_value, buffer[i]);
70f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      return false;
71f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    }
72f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  }
73f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  return true;
74f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris}
75f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris
76fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferrisbool doStrcmpExpectEqual(char *string1, char *string2, int align[4],
77f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris                         int (*test_strcmp)(const char *s1, const char *s2),
78f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris                         bool verbose) {
79fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  char *align_str1 = (char*)getAlignedPtr(string1, align[0], align[1]);
80fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  char *align_str2 = (char*)getAlignedPtr(string2, align[2], align[3]);
81fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
82f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  for (size_t i = 0; i < MAX_STRCMP_TEST_SIZE; i++) {
83f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    for (size_t j = 0; j < i; j++) {
84fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      align_str1[j] = (char)(32 + (j % 96));
85fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      align_str2[j] = align_str1[j];
86fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    }
87fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    align_str1[i] = '\0';
88fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    align_str2[i] = '\0';
89f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris
90fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    // Set the characters after the string terminates to different values
91fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    // to verify that the strcmp is not over checking.
92f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    for (size_t j = i+1; j < i+64; j++) {
93fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      align_str1[j] = (char)(32 + j);
94fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      align_str2[j] = (char)(40 + j);
95fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    }
96fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
97f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    if (verbose) {
98f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      printf("Testing size %d, align_str1=%p[%d,%d], align_str2=%p[%d,%d]\n",
99f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris             i, align_str1, align[0], align[1], align_str2, align[2], align[3]);
100f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    }
101f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris
102fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    if (test_strcmp(align_str1, align_str2) != 0) {
103fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      printf("    Failed at size %d, src1 %p, src2 %p\n",
104fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris             i, align_str1, align_str2);
105f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      return false;
106fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    }
107fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  }
108f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris
109f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  return true;
110fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris}
111fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
112fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferrisbool doStrcmpExpectDiff(char *string1, char *string2, int diff_align[2],
113fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris                        int align[4], char diff_char,
114f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris                        int (*test_strcmp)(const char *s1, const char *s2),
115f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris                        bool verbose) {
116fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  char *align_str1 = (char*)getAlignedPtr(string1, align[0], align[1]);
117fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  char *align_str2 = (char*)getAlignedPtr(string2, align[2], align[3]);
118fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
119fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  for (int i = 0; i < MAX_STRCMP_TEST_SIZE; i++) {
120fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    // Use valid ascii characters, no unprintables characters.
121fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    align_str1[i] = (char)(32 + (i % 96));
122fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    if (align_str1[i] == diff_char) {
123fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      // Assumes that one less than the diff character is still a valid
124fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      // character.
125fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      align_str1[i] = diff_char-1;
126fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    }
127fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    align_str2[i] = align_str1[i];
128fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  }
129fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  align_str1[MAX_STRCMP_TEST_SIZE] = '\0';
130fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  align_str2[MAX_STRCMP_TEST_SIZE] = '\0';
131fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
132fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  // Quick check to make sure that the strcmp knows that everything is
133fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  // equal. If it's so broken that it already thinks the strings are
134fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  // different, then there is no point running any of the other tests.
135fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  if (test_strcmp(align_str1, align_str2) != 0) {
136fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    printf("    strcmp is too broken to do difference testing.\n");
137fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    return false;
138fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  }
139fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
140fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  // Get a pointer into the string at the specified alignment.
141f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  char *bad = (char*)getAlignedPtr(align_str1+MAX_STRCMP_TEST_SIZE/2,
142f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris                                   diff_align[0], diff_align[1]);
143fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
144fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  char saved_char = bad[0];
145fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  bad[0] = diff_char;
146f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris
147f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  if (verbose) {
148f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    printf("Testing difference, align_str1=%p[%d,%d], align_str2=%p[%d,%d]\n",
149f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris           align_str1, align[0], align[1], align_str2, align[2], align[3]);
150f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  }
151fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  if (test_strcmp(align_str1, align_str2) == 0) {
152fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    printf("   Did not miscompare at size %d, src1 %p, src2 %p, diff %p\n",
153fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris           MAX_STRCMP_TEST_SIZE, align_str1, align_str2, bad);
154f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    return false;
155fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  }
156fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  bad[0] = saved_char;
157fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
158fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  // Re-verify that something hasn't gone horribly wrong.
159fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  if (test_strcmp(align_str1, align_str2) != 0) {
160fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    printf("   strcmp is too broken to do difference testing.\n");
161fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    return false;
162fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  }
163fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
164fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  bad = (char*)getAlignedPtr(align_str2+MAX_STRCMP_TEST_SIZE/2, diff_align[0],
165fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris                             diff_align[1]);
166fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  bad[0] = diff_char;
167f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris
168f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  if (verbose) {
169f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    printf("Testing reverse difference, align_str1=%p[%d,%d], align_str2=%p[%d,%d]\n",
170f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris           align_str1, align[0], align[1], align_str2, align[2], align[3]);
171f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  }
172fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  if (test_strcmp(align_str1, align_str2) == 0) {
173fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    printf("    Did not miscompare at size %d, src1 %p, src2 %p, diff %p\n",
174fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris           MAX_STRCMP_TEST_SIZE, align_str1, align_str2, bad);
175f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    return false;
176fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  }
177fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
178f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  return true;
179fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris}
180fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
181f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferrisbool doStrcmpCheckRead(int (*test_strcmp)(const char *s1, const char *s2),
182f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris                       bool verbose) {
183fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  // In order to verify that the strcmp is not reading past the end of the
184fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  // string, create some strings that end near unreadable memory.
185fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  long pagesize = sysconf(_SC_PAGE_SIZE);
186fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  char *memory = (char*)memalign(pagesize, 2 * pagesize);
187fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  if (memory == NULL) {
188fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    perror("Unable to allocate memory.\n");
189fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    return false;
190fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  }
191fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
192fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  // Make the second page unreadable and unwritable.
193fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  if (mprotect(&memory[pagesize], pagesize, PROT_NONE) != 0) {
194fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    perror("Unable to set protection of page.\n");
195fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    return false;
196fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  }
197fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
198f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  size_t max_size = pagesize < MAX_STRCMP_TEST_SIZE ? pagesize-1 : MAX_STRCMP_TEST_SIZE;
199fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  // Allocate an extra byte beyond the string terminator to allow us to
200fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  // extend the string to be larger than our protected string.
201fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  char *other_string = (char *)malloc(max_size+2);
202fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  if (other_string == NULL) {
203fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    perror("Unable to allocate memory.\n");
204fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    return false;
205fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  }
206f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  char *string;
207f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  for (size_t i = 0; i <= max_size; i++) {
208fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    string = &memory[pagesize-i-1];
209f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    for (size_t j = 0; j < i; j++) {
210fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      other_string[j] = (char)(32 + (j % 96));
211fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      string[j] = other_string[j];
212fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    }
213fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    other_string[i] = '\0';
214fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    string[i] = '\0';
215fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
216f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    if (verbose) {
217f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      printf("Testing size %d, strings equal.\n", i);
218f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    }
219fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    if (test_strcmp(other_string, string) != 0) {
220fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      printf("    Failed at size %d, src1 %p, src2 %p\n", i, other_string, string);
221f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      return false;
222f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    }
223f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris
224f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    if (verbose) {
225f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      printf("Testing size %d, strings equal reverse strings.\n", i);
226fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    }
227fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    if (test_strcmp(string, other_string) != 0) {
228fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      printf("    Failed at size %d, src1 %p, src2 %p\n", i, string, other_string);
229f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      return false;
230fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    }
231fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
232fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    // Now make other_string longer than our protected string.
233fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    other_string[i] = '1';
234fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    other_string[i+1] = '\0';
235fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
236f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    if (verbose) {
237f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      printf("Testing size %d, strings not equal.\n", i);
238f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    }
239fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    if (test_strcmp(other_string, string) == 0) {
240fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      printf("    Failed at size %d, src1 %p, src2 %p\n", i, other_string, string);
241f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      return false;
242f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    }
243f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris
244f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    if (verbose) {
245f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      printf("Testing size %d, strings not equal reverse the strings.\n", i);
246fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    }
247fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    if (test_strcmp(string, other_string) == 0) {
248fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      printf("    Failed at size %d, src1 %p, src2 %p\n", i, string, other_string);
249f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      return false;
250fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    }
251fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  }
252f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  return true;
253fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris}
254fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
255f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferrisbool runStrcmpTest(int (*test_strcmp)(const char *s1, const char *s2),
256f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris                   bool verbose) {
257fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  // Allocate two large buffers to hold the two strings.
258fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  char *string1 = reinterpret_cast<char*>(malloc(MAX_STRCMP_BUFFER_SIZE+1));
259fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  char *string2 = reinterpret_cast<char*>(malloc(MAX_STRCMP_BUFFER_SIZE+1));
260fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  if (string1 == NULL || string2 == NULL) {
261fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    perror("Unable to allocate memory.\n");
262fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    return false;
263fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  }
264fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
265fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  // Initialize the strings to be exactly the same.
266fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  for (int i = 0; i < MAX_STRCMP_BUFFER_SIZE; i++) {
267fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    string1[i] = (char)(32 + (i % 96));
268fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    string2[i] = string1[i];
269fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  }
270fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  string1[MAX_STRCMP_BUFFER_SIZE] = '\0';
271fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  string2[MAX_STRCMP_BUFFER_SIZE] = '\0';
272fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
273f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  // Check different string alignments. All zeroes indicates that the
274f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  // unmodified malloc values should be used.
275fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  int string_aligns[][4] = {
276f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    // All zeroes to use the values returned from malloc.
277f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    { 0, 0, 0, 0 },
278f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris
279fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 1, 0, 1, 0 },
280fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 2, 0, 2, 0 },
281fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 0, 4, 0 },
282fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 8, 0, 8, 0 },
283fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
284fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 8, 0, 4, 0 },
285fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 0, 8, 0 },
286fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
287fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 8, 0, 8, 1 },
288fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 8, 0, 8, 2 },
289fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 8, 0, 8, 3 },
290fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 8, 1, 8, 0 },
291fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 8, 2, 8, 0 },
292fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 8, 3, 8, 0 },
293fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
294fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 0, 4, 1 },
295fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 0, 4, 2 },
296fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 0, 4, 3 },
297fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 1, 4, 0 },
298fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 2, 4, 0 },
299fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 3, 4, 0 },
300fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  };
301fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
302fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  printf("  Verifying equal sized strings at different alignments.\n");
303fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  for (size_t i = 0; i < sizeof(string_aligns)/sizeof(int[4]); i++) {
304f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    if (!doStrcmpExpectEqual(string1, string2, string_aligns[i], test_strcmp,
305f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris                             verbose)) {
306f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      return false;
307f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    }
308fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  }
309fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
310f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  // Test the function finds strings with differences at specific locations.
311fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  int diff_aligns[][2] = {
312fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 0 },
313fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 1 },
314fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 2 },
315fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 3 },
316fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 8, 0 },
317fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 8, 1 },
318fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 8, 2 },
319fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 8, 3 },
320fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  };
321fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  printf("  Verifying different strings at different alignments.\n");
322f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  for (size_t i = 0; i < sizeof(diff_aligns)/sizeof(int[2]); i++) {
323fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    // First loop put the string terminator at the chosen alignment.
324f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    for (size_t j = 0; j < sizeof(string_aligns)/sizeof(int[4]); j++) {
325f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      if (!doStrcmpExpectDiff(string1, string2, diff_aligns[i],
326f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris                              string_aligns[j], '\0', test_strcmp, verbose)) {
327f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        return false;
328f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      }
329fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    }
330fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    // Second loop put a different character at the chosen alignment.
331fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    // This character is guaranteed not to be in the original string.
332f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    for (size_t j = 0; j < sizeof(string_aligns)/sizeof(int[4]); j++) {
333f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      if (!doStrcmpExpectDiff(string1, string2, diff_aligns[i],
334f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris                              string_aligns[j], '\0', test_strcmp, verbose)) {
335f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        return false;
336f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      }
337fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    }
338fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  }
339fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
340fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  printf("  Verifying strcmp does not read too many bytes.\n");
341f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  if (!doStrcmpCheckRead(test_strcmp, verbose)) {
342f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    return false;
343fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  }
344fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
345f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  printf("  All tests pass.\n");
346f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris
347f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  return true;
348fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris}
349fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
350f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferrisbool runMemcpyTest(void* (*test_memcpy)(void *dst, const void *src, size_t n),
351f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris                   bool verbose) {
352fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  // Allocate two large buffers to hold the dst and src.
353fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  uint8_t *dst = reinterpret_cast<uint8_t*>(malloc(MAX_MEMCPY_BUFFER_SIZE));
354fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  uint8_t *src = reinterpret_cast<uint8_t*>(malloc(MAX_MEMCPY_BUFFER_SIZE));
355fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  if (dst == NULL || src == NULL) {
356fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    perror("Unable to allocate memory.\n");
357fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    return false;
358fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  }
359fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
360f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  // Set the source to a known pattern once. The assumption is that the
361f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  // memcpy is not so broken that it will write in to the source buffer.
362f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  // However, do not write zeroes into the source so a very quick can be
363f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  // made to verify the source has not been modified.
364fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  for (int i = 0; i < MAX_MEMCPY_BUFFER_SIZE; i++) {
365fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    src[i] = i % 256;
366fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    if (src[i] == 0) {
367fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      src[i] = 0xaa;
368fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    }
369fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  }
370fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
371fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  int aligns[][4] = {
372f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    // Src and dst use pointers returned by malloc.
373f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    { 0, 0, 0, 0 },
374f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris
375f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    // Src and dst at same alignment.
376fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 1, 0, 1, 0 },
377fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 2, 0, 2, 0 },
378fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 0, 4, 0 },
379fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 8, 0, 8, 0 },
380fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 16, 0, 16, 0 },
381fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 32, 0, 32, 0 },
382fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 64, 0, 64, 0 },
383fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 128, 0, 128, 0 },
384fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
385fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    // Different alignments between src and dst.
386fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 8, 0, 4, 0 },
387fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 0, 8, 0 },
388fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 16, 0, 4, 0 },
389fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 0, 16, 0 },
390fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
391fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    // General unaligned cases.
392fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 0, 4, 1 },
393fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 0, 4, 2 },
394fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 0, 4, 3 },
395fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 1, 4, 0 },
396fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 2, 4, 0 },
397fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 3, 4, 0 },
398fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
399fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    // All non-word aligned cases.
400fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 1, 4, 0 },
401fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 1, 4, 1 },
402fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 1, 4, 2 },
403fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 1, 4, 3 },
404fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
405fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 2, 4, 0 },
406fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 2, 4, 1 },
407fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 2, 4, 2 },
408fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 2, 4, 3 },
409fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
410fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 3, 4, 0 },
411fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 3, 4, 1 },
412fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 3, 4, 2 },
413fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 3, 4, 3 },
414fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
415fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 2, 0, 4, 0 },
416fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 0, 2, 0 },
417fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 2, 0, 2, 0 },
418fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
419fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    // Invoke the unaligned case where the code needs to align dst to 0x10.
420fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 128, 1, 128, 4 },
421fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 128, 1, 128, 8 },
422fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 128, 1, 128, 12 },
423fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 128, 1, 128, 16 },
424fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  };
425fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
426fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  printf("  Verifying variable sized copies at different alignments.\n");
427fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  uint8_t *src_align, *dst_align;
428fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  for (size_t i = 0; i < sizeof(aligns)/sizeof(int[4]); i++) {
429f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    for (size_t len = 0; len <= MAX_MEMCPY_TEST_SIZE; len++) {
430f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      if (aligns[i][0]) {
431f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        src_align = (uint8_t*)getAlignedPtr(src+FENCEPOST_LENGTH, aligns[i][0],
432f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris                                            aligns[i][1]);
433f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        dst_align = (uint8_t*)getAlignedPtr(dst+FENCEPOST_LENGTH, aligns[i][2],
434f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris                                            aligns[i][3]);
435f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      } else {
436f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        src_align = src;
437f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        dst_align = dst;
438f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      }
439f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris
440f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      if (verbose) {
441f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        printf("Testing size %d, src_align=%p[%d,%d], dst_align=%p[%d,%d]\n",
442f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris               len, src_align, aligns[i][0], aligns[i][1],
443f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris               dst_align, aligns[i][2], aligns[i][3]);
444f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      }
445f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris
446fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      memset(dst_align, 0, len);
447f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris
448f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      // Don't add a pre fencepost if we are using the value from the malloc.
449f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      if (dst_align != dst) {
4501685d00d0a6b905a820a76c9686b6b4b077dfe4aChristopher Ferris        setFencepost(&dst_align[-8]);
451f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      }
452f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      setFencepost(&dst_align[len]);
453fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
454fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      test_memcpy(dst_align, src_align, len);
455fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
456f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      for (size_t j = 0; j < len; j++) {
457fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris        if (dst_align[j] != src_align[j] || !src_align[j]) {
458fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris          if (!src_align[j]) {
459fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris            printf("    src_align[%d] is 0, memcpy wrote into the source.\n", j);
460f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris          } else {
461f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris            printf("    mismatch at %d, expected %d found %d\n", j,
462f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris                   src_align[j], dst_align[j]);
463fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris          }
464fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris          printf("    Failed at size %d, src_align=%p[%d,%d], dst_align=%p[%d,%d]\n",
465fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris                 len, src_align, aligns[i][0], aligns[i][1],
466fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris                 dst_align, aligns[i][2], aligns[i][3]);
467f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris          return false;
468fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris        }
469fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      }
470f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      if (dst_align != dst && !verifyFencepost(&dst_align[-8])) {
471f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        printf("    wrote before the array.\n");
472f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        printf("    Failed at size %d, src_align=%p[%d,%d], dst_align=%p[%d,%d]\n",
473fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris               len, src_align, aligns[i][0], aligns[i][1],
474f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris               dst_align, aligns[i][2], aligns[i][3]);
475f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        return false;
476f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      }
477f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      if (!verifyFencepost(&dst_align[len])) {
478f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        printf("    wrote past the end of the array.\n");
479f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        printf("    Failed at size %d, src_align=%p[%d,%d], dst_align=%p[%d,%d]\n",
480f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris               len, src_align, aligns[i][0], aligns[i][1],
481f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris               dst_align, aligns[i][2], aligns[i][3]);
482f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        return false;
483fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      }
484fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    }
485fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  }
486fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
487f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  printf("  All tests pass.\n");
488fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
489f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  return true;
490fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris}
491fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
492f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferrisbool runMemsetTest(void* (*test_memset)(void *s, int c, size_t n),
493f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris                   bool verbose) {
494cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris  // Allocate one large buffer to hold the dst.
495cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris  uint8_t *buf = reinterpret_cast<uint8_t*>(malloc(MAX_MEMSET_BUFFER_SIZE));
496cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris  if (buf == NULL) {
497cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    perror("Unable to allocate memory.\n");
498cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    return false;
499cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris  }
500cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris
501cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris  int aligns[][2] = {
502f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    // Use malloc return values unaltered.
503f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    { 0, 0 },
504f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris
505cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    // Different alignments.
506cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    { 1, 0 },
507cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    { 2, 0 },
508cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    { 4, 0 },
509cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    { 8, 0 },
510cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    { 16, 0 },
511cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    { 32, 0 },
512cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    { 64, 0 },
513cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris
514cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    // Different alignments between src and dst.
515cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    { 8, 1 },
516cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    { 8, 2 },
517cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    { 8, 3 },
518cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    { 8, 4 },
519cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    { 8, 5 },
520cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    { 8, 6 },
521cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    { 8, 7 },
522cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris  };
523cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris
524cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris  printf("  Verifying variable sized memsets at different alignments.\n");
525cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris  uint8_t *buf_align;
526cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris  for (size_t i = 0; i < sizeof(aligns)/sizeof(int[2]); i++) {
527f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    for (size_t len = 0; len <= MAX_MEMSET_TEST_SIZE; len++) {
528f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      if (aligns[i]) {
529f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        buf_align = (uint8_t*)getAlignedPtr(buf+FENCEPOST_LENGTH, aligns[i][0],
530f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris                                            aligns[i][1]);
531f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      } else {
532f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        buf_align = buf;
533f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      }
534f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris
535f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      if (verbose) {
536f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        printf("Testing size %d, buf_align=%p[%d,%d]\n",
537f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris               len, buf_align, aligns[i][0], aligns[i][1]);
538f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      }
539cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris
540cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris      // Set the buffer to all zero without memset since it might be the
541cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris      // function we are testing.
542f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      for (size_t j = 0; j < len; j++) {
543cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris        buf_align[j] = 0;
544cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris      }
545cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris
546f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      // Don't add a pre fencepost if we are using the value from the malloc.
547f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      if (buf_align != buf) {
5481685d00d0a6b905a820a76c9686b6b4b077dfe4aChristopher Ferris        setFencepost(&buf_align[-8]);
549f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      }
550f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      setFencepost(&buf_align[len]);
551f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris
552f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      int value = (len % 255) + 1;
553cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris      test_memset(buf_align, value, len);
554cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris
555f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      for (size_t j = 0; j < len; j++) {
556cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris        if (buf_align[j] != value) {
557cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris          printf("    Failed at size %d[%d,%d!=%d], buf_align=%p[%d,%d]\n",
558cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris                 len, j, buf_align[j], value, buf_align, aligns[i][0],
559cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris                 aligns[i][1]);
560f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris          return false;
561cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris        }
562cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris      }
563f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      if (buf_align != buf && !verifyFencepost(&buf_align[-8])) {
564f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        printf("    wrote before the beginning of the array.\n");
565f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        printf("    Failed at size %d, buf_align=%p[%d,%d]\n",
566f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris               len, buf_align, aligns[i][0], aligns[i][1]);
567f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        return false;
568f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      }
569f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      if (!verifyFencepost(&buf_align[len])) {
570f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        printf("    wrote after the end of the array.\n");
571cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris        printf("    Failed at size %d, buf_align=%p[%d,%d]\n",
572cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris               len, buf_align, aligns[i][0], aligns[i][1]);
573f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        return false;
574cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris      }
575cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    }
576cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris  }
577cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris
578f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  printf("  All tests pass.\n");
579cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris
580f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  return true;
581cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris}
582cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris
583fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferrisint main(int argc, char **argv) {
584f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  bool verbose = false;
585f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  if (argc == 2 && strcmp(argv[1], "-v") == 0) {
586f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    verbose = true;
587f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  }
588fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
589f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  bool tests_passing = true;
590fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  printf("Testing strcmp...\n");
591f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  tests_passing = runStrcmpTest(strcmp, verbose) && tests_passing;
592fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
593fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  printf("Testing memcpy...\n");
594f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  tests_passing = runMemcpyTest(memcpy, verbose) && tests_passing;
595fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
596cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris  printf("Testing memset...\n");
597f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  tests_passing = runMemsetTest(memset, verbose) && tests_passing;
598cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris
599fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  return (tests_passing ? 0 : 1);
600fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris}
601