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
341c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris#define MAX_STRING_TEST_SIZE      1024
351c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris#define MAX_STRING_BUFFER_SIZE    (3 * MAX_STRING_TEST_SIZE)
36fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
371c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris#define MAX_STRCAT_DST_SIZE       32
381c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris
391c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferrisconst int kStringAligns[][4] = {
401c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  // All zeroes to use the values returned from malloc.
411c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  { 0, 0, 0, 0 },
421c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris
431c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  { 1, 0, 1, 0 },
441c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  { 2, 0, 2, 0 },
451c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  { 4, 0, 4, 0 },
461c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  { 8, 0, 8, 0 },
471c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris
481c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  { 8, 0, 4, 0 },
491c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  { 4, 0, 8, 0 },
501c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris
511c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  { 8, 0, 8, 1 },
521c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  { 8, 0, 8, 2 },
531c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  { 8, 0, 8, 3 },
541c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  { 8, 1, 8, 0 },
551c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  { 8, 2, 8, 0 },
561c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  { 8, 3, 8, 0 },
571c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris
581c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  { 4, 0, 4, 1 },
591c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  { 4, 0, 4, 2 },
601c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  { 4, 0, 4, 3 },
611c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  { 4, 1, 4, 0 },
621c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  { 4, 2, 4, 0 },
631c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  { 4, 3, 4, 0 },
641c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris};
651c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris
661c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris#define STRING_ALIGN_LEN  (sizeof(kStringAligns)/sizeof(int[4]))
67a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris
68fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris// Return a pointer into the current string with the specified alignment.
69fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferrisvoid *getAlignedPtr(void *orig_ptr, int alignment, int or_mask) {
70fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  uint64_t ptr = reinterpret_cast<uint64_t>(orig_ptr);
71fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  if (alignment > 0) {
72fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      // When setting the alignment, set it to exactly the alignment chosen.
73fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      // The pointer returned will be guaranteed not to be aligned to anything
74fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      // more than that.
75fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      ptr += alignment - (ptr & (alignment - 1));
76fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      ptr |= alignment | or_mask;
77fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  }
78fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
79fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  return reinterpret_cast<void*>(ptr);
80fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris}
81fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
821c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferrischar *setString(char *str, size_t size) {
831c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  for (size_t i = 0; i < size; i++) {
841c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris    str[i] = (char)(32 + (i % 96));
851c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  }
861c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  str[size] = '\0';
871c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris
881c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  return str;
891c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris}
901c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris
911c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferrischar *allocateString() {
921c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  char *str = reinterpret_cast<char*>(malloc(MAX_STRING_BUFFER_SIZE+1));
931c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  if (!str) {
941c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris    return NULL;
951c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  }
961c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris
971c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  return setString(str, MAX_STRING_BUFFER_SIZE);
981c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris}
991c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris
100f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferrisvoid setFencepost(uint8_t *buffer) {
101f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  for (int i = 0; i < FENCEPOST_LENGTH; i += 2) {
102f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    buffer[i] = 0xde;
103f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    buffer[i+1] = 0xad;
104f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  }
105f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris}
106f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris
107f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferrisbool verifyFencepost(uint8_t *buffer) {
108f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  for (int i = 0; i < FENCEPOST_LENGTH; i += 2) {
109f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    if (buffer[i] != 0xde || buffer[i+1] != 0xad) {
110f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      uint8_t expected_value;
111f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      if (buffer[i] == 0xde) {
112f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        i++;
113f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        expected_value = 0xad;
114f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      } else {
115f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        expected_value = 0xde;
116f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      }
1171c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris      printf("    mismatch at fencepost[%d], expected %d found %d\n",
118f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris             i, expected_value, buffer[i]);
119f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      return false;
120f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    }
121f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  }
122f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  return true;
123f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris}
124f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris
1251c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferrisbool doStrcmpExpectEqual(char *string1, char *string2, const int align[4],
126f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris                         int (*test_strcmp)(const char *s1, const char *s2),
127f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris                         bool verbose) {
128fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  char *align_str1 = (char*)getAlignedPtr(string1, align[0], align[1]);
129fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  char *align_str2 = (char*)getAlignedPtr(string2, align[2], align[3]);
130fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
1311c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  for (size_t i = 0; i < MAX_STRING_TEST_SIZE; i++) {
132f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    for (size_t j = 0; j < i; j++) {
133fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      align_str1[j] = (char)(32 + (j % 96));
134fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      align_str2[j] = align_str1[j];
135fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    }
136fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    align_str1[i] = '\0';
137fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    align_str2[i] = '\0';
138f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris
139fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    // Set the characters after the string terminates to different values
140fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    // to verify that the strcmp is not over checking.
141f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    for (size_t j = i+1; j < i+64; j++) {
142fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      align_str1[j] = (char)(32 + j);
143fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      align_str2[j] = (char)(40 + j);
144fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    }
145fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
146f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    if (verbose) {
147f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      printf("Testing size %d, align_str1=%p[%d,%d], align_str2=%p[%d,%d]\n",
148f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris             i, align_str1, align[0], align[1], align_str2, align[2], align[3]);
149f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    }
150f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris
151fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    if (test_strcmp(align_str1, align_str2) != 0) {
152fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      printf("    Failed at size %d, src1 %p, src2 %p\n",
153fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris             i, align_str1, align_str2);
154f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      return false;
155fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    }
156fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  }
157f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris
158f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  return true;
159fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris}
160fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
1611c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferrisbool doStrcmpExpectDiff(char *string1, char *string2, const int diff_align[2],
1621c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris                        const int align[4], char diff_char,
163f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris                        int (*test_strcmp)(const char *s1, const char *s2),
164f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris                        bool verbose) {
165fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  char *align_str1 = (char*)getAlignedPtr(string1, align[0], align[1]);
166fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  char *align_str2 = (char*)getAlignedPtr(string2, align[2], align[3]);
167fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
1681c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  for (int i = 0; i < MAX_STRING_TEST_SIZE; i++) {
169fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    // Use valid ascii characters, no unprintables characters.
170fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    align_str1[i] = (char)(32 + (i % 96));
171fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    if (align_str1[i] == diff_char) {
172fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      // Assumes that one less than the diff character is still a valid
173fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      // character.
174fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      align_str1[i] = diff_char-1;
175fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    }
176fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    align_str2[i] = align_str1[i];
177fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  }
1781c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  align_str1[MAX_STRING_TEST_SIZE] = '\0';
1791c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  align_str2[MAX_STRING_TEST_SIZE] = '\0';
180fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
181fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  // Quick check to make sure that the strcmp knows that everything is
182fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  // equal. If it's so broken that it already thinks the strings are
183fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  // different, then there is no point running any of the other tests.
184fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  if (test_strcmp(align_str1, align_str2) != 0) {
185fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    printf("    strcmp is too broken to do difference testing.\n");
186fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    return false;
187fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  }
188fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
189fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  // Get a pointer into the string at the specified alignment.
1901c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  char *bad = (char*)getAlignedPtr(align_str1+MAX_STRING_TEST_SIZE/2,
191f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris                                   diff_align[0], diff_align[1]);
192fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
193fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  char saved_char = bad[0];
194fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  bad[0] = diff_char;
195f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris
196f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  if (verbose) {
197f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    printf("Testing difference, align_str1=%p[%d,%d], align_str2=%p[%d,%d]\n",
198f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris           align_str1, align[0], align[1], align_str2, align[2], align[3]);
199f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  }
200fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  if (test_strcmp(align_str1, align_str2) == 0) {
201fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    printf("   Did not miscompare at size %d, src1 %p, src2 %p, diff %p\n",
2021c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris           MAX_STRING_TEST_SIZE, align_str1, align_str2, bad);
203f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    return false;
204fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  }
205fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  bad[0] = saved_char;
206fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
207fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  // Re-verify that something hasn't gone horribly wrong.
208fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  if (test_strcmp(align_str1, align_str2) != 0) {
209fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    printf("   strcmp is too broken to do difference testing.\n");
210fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    return false;
211fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  }
212fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
2131c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  bad = (char*)getAlignedPtr(align_str2+MAX_STRING_TEST_SIZE/2, diff_align[0],
214fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris                             diff_align[1]);
215fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  bad[0] = diff_char;
216f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris
217f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  if (verbose) {
218f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    printf("Testing reverse difference, align_str1=%p[%d,%d], align_str2=%p[%d,%d]\n",
219f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris           align_str1, align[0], align[1], align_str2, align[2], align[3]);
220f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  }
221fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  if (test_strcmp(align_str1, align_str2) == 0) {
222fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    printf("    Did not miscompare at size %d, src1 %p, src2 %p, diff %p\n",
2231c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris           MAX_STRING_TEST_SIZE, align_str1, align_str2, bad);
224f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    return false;
225fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  }
226fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
227f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  return true;
228fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris}
229fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
230f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferrisbool doStrcmpCheckRead(int (*test_strcmp)(const char *s1, const char *s2),
231f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris                       bool verbose) {
232fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  // In order to verify that the strcmp is not reading past the end of the
233fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  // string, create some strings that end near unreadable memory.
234fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  long pagesize = sysconf(_SC_PAGE_SIZE);
235fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  char *memory = (char*)memalign(pagesize, 2 * pagesize);
236fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  if (memory == NULL) {
237fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    perror("Unable to allocate memory.\n");
238fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    return false;
239fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  }
240fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
241fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  // Make the second page unreadable and unwritable.
242fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  if (mprotect(&memory[pagesize], pagesize, PROT_NONE) != 0) {
243fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    perror("Unable to set protection of page.\n");
244fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    return false;
245fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  }
246fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
2471c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  size_t max_size = pagesize < MAX_STRING_TEST_SIZE ? pagesize-1 : MAX_STRING_TEST_SIZE;
248fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  // Allocate an extra byte beyond the string terminator to allow us to
249fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  // extend the string to be larger than our protected string.
250fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  char *other_string = (char *)malloc(max_size+2);
251fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  if (other_string == NULL) {
252fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    perror("Unable to allocate memory.\n");
253fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    return false;
254fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  }
255f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  char *string;
256f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  for (size_t i = 0; i <= max_size; i++) {
257fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    string = &memory[pagesize-i-1];
258f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    for (size_t j = 0; j < i; j++) {
259fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      other_string[j] = (char)(32 + (j % 96));
260fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      string[j] = other_string[j];
261fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    }
262fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    other_string[i] = '\0';
263fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    string[i] = '\0';
264fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
265f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    if (verbose) {
266f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      printf("Testing size %d, strings equal.\n", i);
267f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    }
268fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    if (test_strcmp(other_string, string) != 0) {
269fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      printf("    Failed at size %d, src1 %p, src2 %p\n", i, other_string, string);
270f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      return false;
271f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    }
272f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris
273f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    if (verbose) {
274f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      printf("Testing size %d, strings equal reverse strings.\n", i);
275fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    }
276fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    if (test_strcmp(string, other_string) != 0) {
277fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      printf("    Failed at size %d, src1 %p, src2 %p\n", i, string, other_string);
278f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      return false;
279fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    }
280fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
281fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    // Now make other_string longer than our protected string.
282fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    other_string[i] = '1';
283fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    other_string[i+1] = '\0';
284fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
285f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    if (verbose) {
286f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      printf("Testing size %d, strings not equal.\n", i);
287f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    }
288fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    if (test_strcmp(other_string, string) == 0) {
289fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      printf("    Failed at size %d, src1 %p, src2 %p\n", i, other_string, string);
290f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      return false;
291f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    }
292f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris
293f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    if (verbose) {
294f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      printf("Testing size %d, strings not equal reverse the strings.\n", i);
295fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    }
296fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    if (test_strcmp(string, other_string) == 0) {
297fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      printf("    Failed at size %d, src1 %p, src2 %p\n", i, string, other_string);
298f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      return false;
299fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    }
300fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  }
301f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  return true;
302fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris}
303fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
304f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferrisbool runStrcmpTest(int (*test_strcmp)(const char *s1, const char *s2),
305f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris                   bool verbose) {
3061c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  char *string1 = allocateString();
3071c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  char *string2 = allocateString();
308fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  if (string1 == NULL || string2 == NULL) {
309fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    perror("Unable to allocate memory.\n");
310fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    return false;
311fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  }
312fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
313fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  printf("  Verifying equal sized strings at different alignments.\n");
3141c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  for (size_t i = 0; i < STRING_ALIGN_LEN; i++) {
3151c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris    if (!doStrcmpExpectEqual(string1, string2, kStringAligns[i], test_strcmp,
316f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris                             verbose)) {
317f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      return false;
318f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    }
319fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  }
320fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
321f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  // Test the function finds strings with differences at specific locations.
3221c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  const int diff_aligns[][2] = {
323fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 0 },
324fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 1 },
325fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 2 },
326fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 3 },
327fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 8, 0 },
328fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 8, 1 },
329fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 8, 2 },
330fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 8, 3 },
331fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  };
332fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  printf("  Verifying different strings at different alignments.\n");
333f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  for (size_t i = 0; i < sizeof(diff_aligns)/sizeof(int[2]); i++) {
334fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    // First loop put the string terminator at the chosen alignment.
3351c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris    for (size_t j = 0; j < STRING_ALIGN_LEN; j++) {
336f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      if (!doStrcmpExpectDiff(string1, string2, diff_aligns[i],
3371c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris                              kStringAligns[j], '\0', test_strcmp, verbose)) {
338f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        return false;
339f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      }
340fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    }
341fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    // Second loop put a different character at the chosen alignment.
342fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    // This character is guaranteed not to be in the original string.
3431c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris    for (size_t j = 0; j < STRING_ALIGN_LEN; j++) {
344f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      if (!doStrcmpExpectDiff(string1, string2, diff_aligns[i],
3451c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris                              kStringAligns[j], '\0', test_strcmp, verbose)) {
346f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        return false;
347f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      }
348fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    }
349fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  }
350fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
351fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  printf("  Verifying strcmp does not read too many bytes.\n");
352f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  if (!doStrcmpCheckRead(test_strcmp, verbose)) {
353f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    return false;
354fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  }
355fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
356f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  printf("  All tests pass.\n");
357f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris
358f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  return true;
359fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris}
360fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
361a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferrisbool doStrlenCheck(size_t size, char *string, int align, int or_mask,
362a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris                   size_t (*test_strlen)(const char *), bool verbose) {
363a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  char *aligned_string = reinterpret_cast<char*>(getAlignedPtr(string, align, or_mask));
364a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  size_t len;
365a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  if (verbose) {
366a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris    printf("Testing size %d, align=%p[%d,%d]\n", size, aligned_string, align, or_mask);
367a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  }
368a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris
369a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  aligned_string[size] = '\0';
370a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  len = test_strlen(aligned_string);
371a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  if (len != size) {
372a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris    printf("Failed at size %d, length returned %u, align=%p[%d,%d]\n",
373a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris           size, len, aligned_string, align, or_mask);
374a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris    return false;
375a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  }
376a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris
377a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  if (verbose) {
378a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris    printf("Testing size %d with extra zeros after string, align=%p[%d,%d]\n",
379a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris           size, aligned_string, align, or_mask);
380a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  }
381a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris
382a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  for (size_t j = size+1; j <= size+16; j++) {
383a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris    aligned_string[j] = '\0';
384a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  }
385a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris
386a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  len = test_strlen(aligned_string);
387a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  if (len != size) {
388a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris    printf("Failed at size %d, length returned %u with zeroes after string, align=%p[%d,%d]\n",
389a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris           size, len, aligned_string, align, or_mask);
390a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris    return false;
391a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  }
392a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris
393a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  for (size_t j = size; j <= size+16; j++) {
394a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris    aligned_string[j] = (char)(32 + (j % 96));
395a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  }
396a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  return true;
397a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris}
398a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris
399a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferrisbool runStrlenTest(size_t (*test_strlen)(const char *),
400a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris                   bool verbose) {
4011c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  char *string = allocateString();
402a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  if (string == NULL) {
403a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris    perror("Unable to allocate memory.\n");
404a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris    return false;
405a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  }
406a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris
407a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  // Check different string alignments. All zeroes indicates that the
408a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  // unmodified malloc values should be used.
4091c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  const int aligns[][2] = {
410a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris    // All zeroes to use the values returned from malloc.
411a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris    { 0, 0 },
412a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris
413a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris    { 1, 0 },
414a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris    { 2, 0 },
415a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris    { 4, 0 },
416a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris    { 8, 0 },
417a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris    { 16, 0 },
418a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris    { 32, 0 },
419a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris
420a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris    { 8, 1 },
421a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris    { 8, 2 },
422a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris    { 8, 3 },
423a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris
424a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris    { 4, 1 },
425a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris    { 4, 2 },
426a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris    { 4, 3 },
427a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  };
428a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris
429a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  printf("  Verifying string lengths at different alignments.\n");
430a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  for (size_t i = 0; i < sizeof(aligns)/sizeof(int[2]); i++) {
4311c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris    for (size_t j = 0; j <= MAX_STRING_TEST_SIZE; j++) {
432a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris      if (!doStrlenCheck(j, string, aligns[i][0], aligns[i][1], test_strlen, verbose)) {
433a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris        return false;
434a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris      }
435a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris    }
436a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  }
437a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris
438a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  printf("  Verifying strlen does not read past end of string.\n");
439a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris
440a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  // In order to verify that strlen is not reading past the end of the
441a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  // string, create strings that end near unreadable memory.
442a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  long pagesize = sysconf(_SC_PAGE_SIZE);
443a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  char *memory = (char*)memalign(pagesize, 2 * pagesize);
444a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  if (memory == NULL) {
445a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris    perror("Unable to allocate memory.\n");
446a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris    return false;
447a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  }
448a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris
449a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  // Make the second page unreadable and unwritable.
450a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  if (mprotect(&memory[pagesize], pagesize, PROT_NONE) != 0) {
451a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris    perror("Unable to set protection of page.\n");
452a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris    return false;
453a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  }
454a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris
4551c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  size_t max_size = pagesize < MAX_STRING_TEST_SIZE ? pagesize-1 : MAX_STRING_TEST_SIZE;
456a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  for (long i = 0; i < pagesize; i++) {
457a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris    memory[i] = (char)(32 + (i % 96));
458a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  }
459a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris
460a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  size_t len;
461a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  for (size_t i = 0; i < sizeof(aligns)/sizeof(int[2]); i++) {
462a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris    for (size_t j = 0; j <= max_size; j++) {
463a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris      string = &memory[pagesize-j-1];
464a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris      string[j] = '\0';
465a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris
466a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris      if (verbose) {
467a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris        printf("Testing size %d overread, align=%p[%d,%d]\n",
468a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris               j, string, aligns[i][0], aligns[i][1]);
469a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris      }
470a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris      len = test_strlen(string);
471a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris      if (len != j) {
472a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris        printf("    Failed at size %u, returned %u, align=%p[%d,%d]\n",
473a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris               j, len, string, aligns[i][0], aligns[i][1]);
474a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris        return false;
475a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris      }
476a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris      string[j] = (char)(32 + (j % 96));
477a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris    }
478a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  }
479a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris
480a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  printf("  All tests pass.\n");
481a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris
482a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  return true;
483a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris}
484a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris
4851c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferrisbool runStrcpyTest(char *(*test_strcpy)(char *, const char *),
4861c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris                   bool verbose) {
4871c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  char *src = allocateString();
4881c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  if (src == NULL) {
4891c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris    perror("Unable to allocate memory.\n");
4901c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris    return false;
4911c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  }
4921c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  char *dst = allocateString();
4931c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  if (dst == NULL) {
4941c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris    perror("Unable to allocate memory.\n");
4951c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris    return false;
4961c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  }
4971c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris
4981c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  printf("  Verifying string lengths at different alignments.\n");
4991c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  char *src_align;
5001c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  char *dst_align;
5011c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  char *dst_ret;
5021c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  for (size_t i = 0; i < STRING_ALIGN_LEN; i++) {
5031c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris    for (size_t copy_len = 0; copy_len <= MAX_STRING_TEST_SIZE; copy_len++) {
5041c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris      if (kStringAligns[i][0]) {
5051c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris        src_align = reinterpret_cast<char*>(getAlignedPtr(src+FENCEPOST_LENGTH, kStringAligns[i][0], kStringAligns[i][1]));
5061c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris        dst_align = reinterpret_cast<char*>(getAlignedPtr(dst+FENCEPOST_LENGTH, kStringAligns[i][2], kStringAligns[i][3]));
5071c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris      } else {
5081c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris        src_align = src;
5091c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris        dst_align = dst;
5101c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris      }
5111c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris      setString(src_align, copy_len);
5121c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris      memset(dst_align, 0, copy_len+1);
5131c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris
5141c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris      if (dst_align != dst) {
5151c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris        setFencepost(reinterpret_cast<uint8_t*>(&dst_align[-FENCEPOST_LENGTH]));
5161c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris      }
5171c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris      setFencepost(reinterpret_cast<uint8_t*>(&dst_align[copy_len+1]));
5181c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris
5191c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris      if (verbose) {
5201c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris        printf("Testing copy_len %u, src_align=%p[%d,%d], dst_align=%p[%d,%d]\n",
5211c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris               copy_len, src_align, kStringAligns[i][0], kStringAligns[i][1],
5221c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris               dst_align, kStringAligns[i][2], kStringAligns[i][3]);
5231c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris      }
5241c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris
5251c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris      dst_ret = test_strcpy(dst_align, src_align);
5261c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris      if (dst_ret != dst_align) {
5271c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris        printf("copy_len %u returned incorrect value: expected %p, got %p\n",
5281c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris               copy_len, dst_align, dst_ret);
5291c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris        return false;
5301c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris      }
5311c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris      if (memcmp(src_align, dst_align, copy_len) != 0) {
5321c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris        printf("copy_len %u failed to copy properly: src and dst aren't equal\n", copy_len);
5331c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris        return false;
5341c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris      }
5351c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris
5361c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris      if (dst_align != dst && !verifyFencepost(reinterpret_cast<uint8_t*>(&dst_align[-FENCEPOST_LENGTH]))) {
5371c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris        printf("copy_len %u fencepost before dst was overwritten\n", copy_len);
5381c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris        return false;
5391c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris      }
5401c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris
5411c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris      if (!verifyFencepost(reinterpret_cast<uint8_t*>(&dst_align[copy_len+1]))) {
5421c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris        printf("copy_len %u fencepost at end of dst was overwritten\n", copy_len);
5431c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris        return false;
5441c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris      }
5451c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris    }
5461c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  }
5471c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris
5481c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  printf("  All tests pass.\n");
5491c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris
5501c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  return true;
5511c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris}
5521c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris
5531c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferrisbool runStrcatTest(char *(*test_strcat)(char *, const char *),
5541c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris                   bool verbose) {
5551c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  char *src = allocateString();
5561c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  if (src == NULL) {
5571c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris    perror("Unable to allocate memory.\n");
5581c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris    return false;
5591c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  }
5601c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  char *dst = allocateString();
5611c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  if (dst == NULL) {
5621c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris    perror("Unable to allocate memory.\n");
5631c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris    return false;
5641c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  }
5651c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris
5661c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  printf("  Verifying string lengths at different alignments.\n");
5671c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  char *src_align;
5681c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  char *dst_align;
5691c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  char *dst_ret;
5701c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  for (size_t i = 0; i < STRING_ALIGN_LEN; i++) {
5711c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris    for (size_t dst_len = 0; dst_len <= MAX_STRCAT_DST_SIZE; dst_len++) {
5721c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris      for (size_t copy_len = 0; copy_len <= MAX_STRING_TEST_SIZE; copy_len++) {
5731c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris        if (kStringAligns[i][0]) {
5741c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris          src_align = reinterpret_cast<char*>(getAlignedPtr(src+FENCEPOST_LENGTH, kStringAligns[i][0], kStringAligns[i][1]));
5751c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris          dst_align = reinterpret_cast<char*>(getAlignedPtr(dst+FENCEPOST_LENGTH, kStringAligns[i][2], kStringAligns[i][3]));
5761c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris        } else {
5771c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris          src_align = src;
5781c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris          dst_align = dst;
5791c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris        }
5801c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris        setString(src_align, copy_len);
5811c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris        memset(dst_align, 'd', dst_len);
5821c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris        memset(dst_align+dst_len, 0, copy_len+1);
5831c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris
5841c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris        if (dst_align != dst) {
5851c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris          setFencepost(reinterpret_cast<uint8_t*>(&dst_align[-FENCEPOST_LENGTH]));
5861c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris        }
5871c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris        setFencepost(reinterpret_cast<uint8_t*>(&dst_align[copy_len+dst_len+1]));
5881c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris
5891c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris        if (verbose) {
5901c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris          printf("Testing copy_len %u, dst_len %u, src_align=%p[%d,%d], dst_align=%p[%d,%d]\n",
5911c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris                 copy_len, dst_len, src_align, kStringAligns[i][0], kStringAligns[i][1],
5921c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris                 dst_align, kStringAligns[i][2], kStringAligns[i][3]);
5931c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris        }
5941c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris
5951c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris        dst_ret = test_strcat(dst_align, src_align);
5961c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris        if (dst_ret != dst_align) {
5971c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris          printf("dst_len %u, copy_len %u returned incorrect value: expected %p, got %p\n",
5981c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris                dst_len, copy_len, dst_align, dst_ret);
5991c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris          return false;
6001c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris        }
6011c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris        for (size_t j = 0; j < dst_len; j++) {
6021c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris          if (dst_align[j] != 'd') {
6031c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris            printf("dst_len %u, copy_len %u: strcat overwrote dst string\n",
6041c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris                   dst_len, copy_len);
6051c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris            return false;
6061c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris          }
6071c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris        }
6081c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris        if (memcmp(src_align, dst_align+dst_len, copy_len+1) != 0) {
6091c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris          printf("dst_len %u, copy_len %u failed to copy properly: src and dst aren't equal\n",
6101c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris                 dst_len, copy_len);
6111c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris          return false;
6121c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris        }
6131c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris
6141c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris        if (dst_align != dst && !verifyFencepost(reinterpret_cast<uint8_t*>(&dst_align[-FENCEPOST_LENGTH]))) {
6151c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris          return false;
6161c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris        }
6171c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris
6181c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris        if (!verifyFencepost(reinterpret_cast<uint8_t*>(&dst_align[dst_len+copy_len+1]))) {
6191c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris          return false;
6201c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris        }
6211c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris      }
6221c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris    }
6231c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  }
6241c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris
6251c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  printf("  All tests pass.\n");
6261c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris
6271c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  return true;
6281c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris}
6291c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris
630f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferrisbool runMemcpyTest(void* (*test_memcpy)(void *dst, const void *src, size_t n),
631f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris                   bool verbose) {
632fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  uint8_t *dst = reinterpret_cast<uint8_t*>(malloc(MAX_MEMCPY_BUFFER_SIZE));
633fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  uint8_t *src = reinterpret_cast<uint8_t*>(malloc(MAX_MEMCPY_BUFFER_SIZE));
634fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  if (dst == NULL || src == NULL) {
635fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    perror("Unable to allocate memory.\n");
636fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    return false;
637fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  }
638fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
639f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  // Set the source to a known pattern once. The assumption is that the
640f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  // memcpy is not so broken that it will write in to the source buffer.
641f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  // However, do not write zeroes into the source so a very quick can be
642f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  // made to verify the source has not been modified.
643fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  for (int i = 0; i < MAX_MEMCPY_BUFFER_SIZE; i++) {
644fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    src[i] = i % 256;
645fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    if (src[i] == 0) {
646fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      src[i] = 0xaa;
647fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    }
648fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  }
649fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
6501c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  const int aligns[][4] = {
651f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    // Src and dst use pointers returned by malloc.
652f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    { 0, 0, 0, 0 },
653f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris
654f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    // Src and dst at same alignment.
655fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 1, 0, 1, 0 },
656fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 2, 0, 2, 0 },
657fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 0, 4, 0 },
658fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 8, 0, 8, 0 },
659fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 16, 0, 16, 0 },
660fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 32, 0, 32, 0 },
661fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 64, 0, 64, 0 },
662fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 128, 0, 128, 0 },
663fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
664fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    // Different alignments between src and dst.
665fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 8, 0, 4, 0 },
666fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 0, 8, 0 },
667fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 16, 0, 4, 0 },
668fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 0, 16, 0 },
669fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
670fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    // General unaligned cases.
671fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 0, 4, 1 },
672fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 0, 4, 2 },
673fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 0, 4, 3 },
674fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 1, 4, 0 },
675fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 2, 4, 0 },
676fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 3, 4, 0 },
677fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
678fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    // All non-word aligned cases.
679fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 1, 4, 0 },
680fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 1, 4, 1 },
681fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 1, 4, 2 },
682fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 1, 4, 3 },
683fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
684fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 2, 4, 0 },
685fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 2, 4, 1 },
686fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 2, 4, 2 },
687fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 2, 4, 3 },
688fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
689fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 3, 4, 0 },
690fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 3, 4, 1 },
691fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 3, 4, 2 },
692fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 3, 4, 3 },
693fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
694fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 2, 0, 4, 0 },
695fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 4, 0, 2, 0 },
696fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 2, 0, 2, 0 },
697fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
698fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    // Invoke the unaligned case where the code needs to align dst to 0x10.
699fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 128, 1, 128, 4 },
700fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 128, 1, 128, 8 },
701fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 128, 1, 128, 12 },
702fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    { 128, 1, 128, 16 },
703fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  };
704fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
705fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  printf("  Verifying variable sized copies at different alignments.\n");
706fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  uint8_t *src_align, *dst_align;
707fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  for (size_t i = 0; i < sizeof(aligns)/sizeof(int[4]); i++) {
708f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    for (size_t len = 0; len <= MAX_MEMCPY_TEST_SIZE; len++) {
709f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      if (aligns[i][0]) {
710f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        src_align = (uint8_t*)getAlignedPtr(src+FENCEPOST_LENGTH, aligns[i][0],
711f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris                                            aligns[i][1]);
712f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        dst_align = (uint8_t*)getAlignedPtr(dst+FENCEPOST_LENGTH, aligns[i][2],
713f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris                                            aligns[i][3]);
714f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      } else {
715f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        src_align = src;
716f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        dst_align = dst;
717f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      }
718f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris
719f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      if (verbose) {
720f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        printf("Testing size %d, src_align=%p[%d,%d], dst_align=%p[%d,%d]\n",
721f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris               len, src_align, aligns[i][0], aligns[i][1],
722f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris               dst_align, aligns[i][2], aligns[i][3]);
723f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      }
724f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris
725fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      memset(dst_align, 0, len);
726f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris
727f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      // Don't add a pre fencepost if we are using the value from the malloc.
728f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      if (dst_align != dst) {
7291685d00d0a6b905a820a76c9686b6b4b077dfe4aChristopher Ferris        setFencepost(&dst_align[-8]);
730f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      }
731f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      setFencepost(&dst_align[len]);
732fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
733fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      test_memcpy(dst_align, src_align, len);
734fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
735f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      for (size_t j = 0; j < len; j++) {
736fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris        if (dst_align[j] != src_align[j] || !src_align[j]) {
737fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris          if (!src_align[j]) {
738fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris            printf("    src_align[%d] is 0, memcpy wrote into the source.\n", j);
739f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris          } else {
740f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris            printf("    mismatch at %d, expected %d found %d\n", j,
741f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris                   src_align[j], dst_align[j]);
742fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris          }
743fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris          printf("    Failed at size %d, src_align=%p[%d,%d], dst_align=%p[%d,%d]\n",
744fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris                 len, src_align, aligns[i][0], aligns[i][1],
745fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris                 dst_align, aligns[i][2], aligns[i][3]);
746f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris          return false;
747fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris        }
748fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      }
749f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      if (dst_align != dst && !verifyFencepost(&dst_align[-8])) {
750f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        printf("    wrote before the array.\n");
751f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        printf("    Failed at size %d, src_align=%p[%d,%d], dst_align=%p[%d,%d]\n",
752fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris               len, src_align, aligns[i][0], aligns[i][1],
753f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris               dst_align, aligns[i][2], aligns[i][3]);
754f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        return false;
755f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      }
756f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      if (!verifyFencepost(&dst_align[len])) {
757f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        printf("    wrote past the end of the array.\n");
758f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        printf("    Failed at size %d, src_align=%p[%d,%d], dst_align=%p[%d,%d]\n",
759f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris               len, src_align, aligns[i][0], aligns[i][1],
760f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris               dst_align, aligns[i][2], aligns[i][3]);
761f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        return false;
762fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris      }
763fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris    }
764fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  }
765fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
766f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  printf("  All tests pass.\n");
767fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
768f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  return true;
769fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris}
770fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
771f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferrisbool runMemsetTest(void* (*test_memset)(void *s, int c, size_t n),
772f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris                   bool verbose) {
773cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris  uint8_t *buf = reinterpret_cast<uint8_t*>(malloc(MAX_MEMSET_BUFFER_SIZE));
774cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris  if (buf == NULL) {
775cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    perror("Unable to allocate memory.\n");
776cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    return false;
777cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris  }
778cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris
7791c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  const int aligns[][2] = {
780f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    // Use malloc return values unaltered.
781f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    { 0, 0 },
782f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris
783cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    // Different alignments.
784cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    { 1, 0 },
785cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    { 2, 0 },
786cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    { 4, 0 },
787cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    { 8, 0 },
788cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    { 16, 0 },
789cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    { 32, 0 },
790cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    { 64, 0 },
791cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris
792cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    // Different alignments between src and dst.
793cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    { 8, 1 },
794cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    { 8, 2 },
795cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    { 8, 3 },
796cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    { 8, 4 },
797cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    { 8, 5 },
798cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    { 8, 6 },
799cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    { 8, 7 },
800cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris  };
801cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris
802cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris  printf("  Verifying variable sized memsets at different alignments.\n");
803cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris  uint8_t *buf_align;
804cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris  for (size_t i = 0; i < sizeof(aligns)/sizeof(int[2]); i++) {
805f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    for (size_t len = 0; len <= MAX_MEMSET_TEST_SIZE; len++) {
806f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      if (aligns[i]) {
807f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        buf_align = (uint8_t*)getAlignedPtr(buf+FENCEPOST_LENGTH, aligns[i][0],
808f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris                                            aligns[i][1]);
809f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      } else {
810f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        buf_align = buf;
811f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      }
812f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris
813f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      if (verbose) {
814f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        printf("Testing size %d, buf_align=%p[%d,%d]\n",
815f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris               len, buf_align, aligns[i][0], aligns[i][1]);
816f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      }
817cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris
818cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris      // Set the buffer to all zero without memset since it might be the
819cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris      // function we are testing.
820f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      for (size_t j = 0; j < len; j++) {
821cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris        buf_align[j] = 0;
822cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris      }
823cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris
824f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      // Don't add a pre fencepost if we are using the value from the malloc.
825f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      if (buf_align != buf) {
8261685d00d0a6b905a820a76c9686b6b4b077dfe4aChristopher Ferris        setFencepost(&buf_align[-8]);
827f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      }
828f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      setFencepost(&buf_align[len]);
829f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris
830f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      int value = (len % 255) + 1;
831cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris      test_memset(buf_align, value, len);
832cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris
833f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      for (size_t j = 0; j < len; j++) {
834cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris        if (buf_align[j] != value) {
835cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris          printf("    Failed at size %d[%d,%d!=%d], buf_align=%p[%d,%d]\n",
836cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris                 len, j, buf_align[j], value, buf_align, aligns[i][0],
837cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris                 aligns[i][1]);
838f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris          return false;
839cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris        }
840cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris      }
841f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      if (buf_align != buf && !verifyFencepost(&buf_align[-8])) {
842f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        printf("    wrote before the beginning of the array.\n");
843f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        printf("    Failed at size %d, buf_align=%p[%d,%d]\n",
844f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris               len, buf_align, aligns[i][0], aligns[i][1]);
845f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        return false;
846f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      }
847f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris      if (!verifyFencepost(&buf_align[len])) {
848f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        printf("    wrote after the end of the array.\n");
849cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris        printf("    Failed at size %d, buf_align=%p[%d,%d]\n",
850cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris               len, buf_align, aligns[i][0], aligns[i][1]);
851f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris        return false;
852cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris      }
853cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris    }
854cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris  }
855cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris
856f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  printf("  All tests pass.\n");
857cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris
858f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  return true;
859cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris}
860cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris
861fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferrisint main(int argc, char **argv) {
862f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  bool verbose = false;
863f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  if (argc == 2 && strcmp(argv[1], "-v") == 0) {
864f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris    verbose = true;
865f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  }
866fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
867f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  bool tests_passing = true;
868a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris
869fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  printf("Testing strcmp...\n");
870f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  tests_passing = runStrcmpTest(strcmp, verbose) && tests_passing;
871fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
872fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  printf("Testing memcpy...\n");
873f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  tests_passing = runMemcpyTest(memcpy, verbose) && tests_passing;
874fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris
875cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris  printf("Testing memset...\n");
876f0b2c68c83e6ced8f988f014bc235393ca231958Christopher Ferris  tests_passing = runMemsetTest(memset, verbose) && tests_passing;
877cd0530e6b72ed9ff4c38f15feea0f231c710af1fChristopher Ferris
878a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  printf("Testing strlen...\n");
879a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris  tests_passing = runStrlenTest(strlen, verbose) && tests_passing;
880a63c049f23c49b6345bf2c845a415109c5471ebeChristopher Ferris
8811c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  printf("Testing strcpy...\n");
8821c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  tests_passing = runStrcpyTest(strcpy, verbose) && tests_passing;
8831c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris
8841c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  printf("Testing strcat...\n");
8851c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris  tests_passing = runStrcatTest(strcat, verbose) && tests_passing;
8861c33ae7ce88efc23b627f5fdb74afc461fc8e4f5Christopher Ferris
887fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris  return (tests_passing ? 0 : 1);
888fd65a4e22d8afef028b84c018519468a5f6545f0Christopher Ferris}
889