#define MAX_MEMSET_TEST_SIZE 2048
#define MAX_MEMSET_BUFFER_SIZE (3 * MAX_MEMSET_TEST_SIZE)
-#define MAX_STRCMP_TEST_SIZE 1024
-#define MAX_STRCMP_BUFFER_SIZE (3 * MAX_STRCMP_TEST_SIZE)
+#define MAX_STRING_TEST_SIZE 1024
+#define MAX_STRING_BUFFER_SIZE (3 * MAX_STRING_TEST_SIZE)
-#define MAX_STRLEN_TEST_SIZE 1024
-#define MAX_STRLEN_BUFFER_SIZE (3 * MAX_STRLEN_TEST_SIZE)
+#define MAX_STRCAT_DST_SIZE 32
+
+const int kStringAligns[][4] = {
+ // All zeroes to use the values returned from malloc.
+ { 0, 0, 0, 0 },
+
+ { 1, 0, 1, 0 },
+ { 2, 0, 2, 0 },
+ { 4, 0, 4, 0 },
+ { 8, 0, 8, 0 },
+
+ { 8, 0, 4, 0 },
+ { 4, 0, 8, 0 },
+
+ { 8, 0, 8, 1 },
+ { 8, 0, 8, 2 },
+ { 8, 0, 8, 3 },
+ { 8, 1, 8, 0 },
+ { 8, 2, 8, 0 },
+ { 8, 3, 8, 0 },
+
+ { 4, 0, 4, 1 },
+ { 4, 0, 4, 2 },
+ { 4, 0, 4, 3 },
+ { 4, 1, 4, 0 },
+ { 4, 2, 4, 0 },
+ { 4, 3, 4, 0 },
+};
+
+#define STRING_ALIGN_LEN (sizeof(kStringAligns)/sizeof(int[4]))
// Return a pointer into the current string with the specified alignment.
void *getAlignedPtr(void *orig_ptr, int alignment, int or_mask) {
return reinterpret_cast<void*>(ptr);
}
+char *setString(char *str, size_t size) {
+ for (size_t i = 0; i < size; i++) {
+ str[i] = (char)(32 + (i % 96));
+ }
+ str[size] = '\0';
+
+ return str;
+}
+
+char *allocateString() {
+ char *str = reinterpret_cast<char*>(malloc(MAX_STRING_BUFFER_SIZE+1));
+ if (!str) {
+ return NULL;
+ }
+
+ return setString(str, MAX_STRING_BUFFER_SIZE);
+}
+
void setFencepost(uint8_t *buffer) {
for (int i = 0; i < FENCEPOST_LENGTH; i += 2) {
buffer[i] = 0xde;
} else {
expected_value = 0xde;
}
- printf(" mismatch at fencepost[%d], expected %d found %d\n",
+ printf(" mismatch at fencepost[%d], expected %d found %d\n",
i, expected_value, buffer[i]);
return false;
}
return true;
}
-bool doStrcmpExpectEqual(char *string1, char *string2, int align[4],
+bool doStrcmpExpectEqual(char *string1, char *string2, const int align[4],
int (*test_strcmp)(const char *s1, const char *s2),
bool verbose) {
char *align_str1 = (char*)getAlignedPtr(string1, align[0], align[1]);
char *align_str2 = (char*)getAlignedPtr(string2, align[2], align[3]);
- for (size_t i = 0; i < MAX_STRCMP_TEST_SIZE; i++) {
+ for (size_t i = 0; i < MAX_STRING_TEST_SIZE; i++) {
for (size_t j = 0; j < i; j++) {
align_str1[j] = (char)(32 + (j % 96));
align_str2[j] = align_str1[j];
return true;
}
-bool doStrcmpExpectDiff(char *string1, char *string2, int diff_align[2],
- int align[4], char diff_char,
+bool doStrcmpExpectDiff(char *string1, char *string2, const int diff_align[2],
+ const int align[4], char diff_char,
int (*test_strcmp)(const char *s1, const char *s2),
bool verbose) {
char *align_str1 = (char*)getAlignedPtr(string1, align[0], align[1]);
char *align_str2 = (char*)getAlignedPtr(string2, align[2], align[3]);
- for (int i = 0; i < MAX_STRCMP_TEST_SIZE; i++) {
+ for (int i = 0; i < MAX_STRING_TEST_SIZE; i++) {
// Use valid ascii characters, no unprintables characters.
align_str1[i] = (char)(32 + (i % 96));
if (align_str1[i] == diff_char) {
}
align_str2[i] = align_str1[i];
}
- align_str1[MAX_STRCMP_TEST_SIZE] = '\0';
- align_str2[MAX_STRCMP_TEST_SIZE] = '\0';
+ align_str1[MAX_STRING_TEST_SIZE] = '\0';
+ align_str2[MAX_STRING_TEST_SIZE] = '\0';
// Quick check to make sure that the strcmp knows that everything is
// equal. If it's so broken that it already thinks the strings are
}
// Get a pointer into the string at the specified alignment.
- char *bad = (char*)getAlignedPtr(align_str1+MAX_STRCMP_TEST_SIZE/2,
+ char *bad = (char*)getAlignedPtr(align_str1+MAX_STRING_TEST_SIZE/2,
diff_align[0], diff_align[1]);
char saved_char = bad[0];
}
if (test_strcmp(align_str1, align_str2) == 0) {
printf(" Did not miscompare at size %d, src1 %p, src2 %p, diff %p\n",
- MAX_STRCMP_TEST_SIZE, align_str1, align_str2, bad);
+ MAX_STRING_TEST_SIZE, align_str1, align_str2, bad);
return false;
}
bad[0] = saved_char;
return false;
}
- bad = (char*)getAlignedPtr(align_str2+MAX_STRCMP_TEST_SIZE/2, diff_align[0],
+ bad = (char*)getAlignedPtr(align_str2+MAX_STRING_TEST_SIZE/2, diff_align[0],
diff_align[1]);
bad[0] = diff_char;
}
if (test_strcmp(align_str1, align_str2) == 0) {
printf(" Did not miscompare at size %d, src1 %p, src2 %p, diff %p\n",
- MAX_STRCMP_TEST_SIZE, align_str1, align_str2, bad);
+ MAX_STRING_TEST_SIZE, align_str1, align_str2, bad);
return false;
}
return false;
}
- size_t max_size = pagesize < MAX_STRCMP_TEST_SIZE ? pagesize-1 : MAX_STRCMP_TEST_SIZE;
+ size_t max_size = pagesize < MAX_STRING_TEST_SIZE ? pagesize-1 : MAX_STRING_TEST_SIZE;
// Allocate an extra byte beyond the string terminator to allow us to
// extend the string to be larger than our protected string.
char *other_string = (char *)malloc(max_size+2);
bool runStrcmpTest(int (*test_strcmp)(const char *s1, const char *s2),
bool verbose) {
- // Allocate two large buffers to hold the two strings.
- char *string1 = reinterpret_cast<char*>(malloc(MAX_STRCMP_BUFFER_SIZE+1));
- char *string2 = reinterpret_cast<char*>(malloc(MAX_STRCMP_BUFFER_SIZE+1));
+ char *string1 = allocateString();
+ char *string2 = allocateString();
if (string1 == NULL || string2 == NULL) {
perror("Unable to allocate memory.\n");
return false;
}
- // Initialize the strings to be exactly the same.
- for (int i = 0; i < MAX_STRCMP_BUFFER_SIZE; i++) {
- string1[i] = (char)(32 + (i % 96));
- string2[i] = string1[i];
- }
- string1[MAX_STRCMP_BUFFER_SIZE] = '\0';
- string2[MAX_STRCMP_BUFFER_SIZE] = '\0';
-
- // Check different string alignments. All zeroes indicates that the
- // unmodified malloc values should be used.
- int string_aligns[][4] = {
- // All zeroes to use the values returned from malloc.
- { 0, 0, 0, 0 },
-
- { 1, 0, 1, 0 },
- { 2, 0, 2, 0 },
- { 4, 0, 4, 0 },
- { 8, 0, 8, 0 },
-
- { 8, 0, 4, 0 },
- { 4, 0, 8, 0 },
-
- { 8, 0, 8, 1 },
- { 8, 0, 8, 2 },
- { 8, 0, 8, 3 },
- { 8, 1, 8, 0 },
- { 8, 2, 8, 0 },
- { 8, 3, 8, 0 },
-
- { 4, 0, 4, 1 },
- { 4, 0, 4, 2 },
- { 4, 0, 4, 3 },
- { 4, 1, 4, 0 },
- { 4, 2, 4, 0 },
- { 4, 3, 4, 0 },
- };
-
printf(" Verifying equal sized strings at different alignments.\n");
- for (size_t i = 0; i < sizeof(string_aligns)/sizeof(int[4]); i++) {
- if (!doStrcmpExpectEqual(string1, string2, string_aligns[i], test_strcmp,
+ for (size_t i = 0; i < STRING_ALIGN_LEN; i++) {
+ if (!doStrcmpExpectEqual(string1, string2, kStringAligns[i], test_strcmp,
verbose)) {
return false;
}
}
// Test the function finds strings with differences at specific locations.
- int diff_aligns[][2] = {
+ const int diff_aligns[][2] = {
{ 4, 0 },
{ 4, 1 },
{ 4, 2 },
printf(" Verifying different strings at different alignments.\n");
for (size_t i = 0; i < sizeof(diff_aligns)/sizeof(int[2]); i++) {
// First loop put the string terminator at the chosen alignment.
- for (size_t j = 0; j < sizeof(string_aligns)/sizeof(int[4]); j++) {
+ for (size_t j = 0; j < STRING_ALIGN_LEN; j++) {
if (!doStrcmpExpectDiff(string1, string2, diff_aligns[i],
- string_aligns[j], '\0', test_strcmp, verbose)) {
+ kStringAligns[j], '\0', test_strcmp, verbose)) {
return false;
}
}
// Second loop put a different character at the chosen alignment.
// This character is guaranteed not to be in the original string.
- for (size_t j = 0; j < sizeof(string_aligns)/sizeof(int[4]); j++) {
+ for (size_t j = 0; j < STRING_ALIGN_LEN; j++) {
if (!doStrcmpExpectDiff(string1, string2, diff_aligns[i],
- string_aligns[j], '\0', test_strcmp, verbose)) {
+ kStringAligns[j], '\0', test_strcmp, verbose)) {
return false;
}
}
bool runStrlenTest(size_t (*test_strlen)(const char *),
bool verbose) {
- // Allocate two large buffers to hold the two strings.
- char *string = reinterpret_cast<char*>(malloc(MAX_STRLEN_BUFFER_SIZE+1));
+ char *string = allocateString();
if (string == NULL) {
perror("Unable to allocate memory.\n");
return false;
}
- // Initialize the strings to be exactly the same.
- for (int i = 0; i < MAX_STRLEN_BUFFER_SIZE; i++) {
- string[i] = (char)(32 + (i % 96));
- }
- string[MAX_STRLEN_BUFFER_SIZE] = '\0';
-
// Check different string alignments. All zeroes indicates that the
// unmodified malloc values should be used.
- int aligns[][2] = {
+ const int aligns[][2] = {
// All zeroes to use the values returned from malloc.
{ 0, 0 },
printf(" Verifying string lengths at different alignments.\n");
for (size_t i = 0; i < sizeof(aligns)/sizeof(int[2]); i++) {
- for (size_t j = 0; j <= MAX_STRLEN_TEST_SIZE; j++) {
+ for (size_t j = 0; j <= MAX_STRING_TEST_SIZE; j++) {
if (!doStrlenCheck(j, string, aligns[i][0], aligns[i][1], test_strlen, verbose)) {
return false;
}
return false;
}
- size_t max_size = pagesize < MAX_STRLEN_TEST_SIZE ? pagesize-1 : MAX_STRLEN_TEST_SIZE;
+ size_t max_size = pagesize < MAX_STRING_TEST_SIZE ? pagesize-1 : MAX_STRING_TEST_SIZE;
for (long i = 0; i < pagesize; i++) {
memory[i] = (char)(32 + (i % 96));
}
return true;
}
+bool runStrcpyTest(char *(*test_strcpy)(char *, const char *),
+ bool verbose) {
+ char *src = allocateString();
+ if (src == NULL) {
+ perror("Unable to allocate memory.\n");
+ return false;
+ }
+ char *dst = allocateString();
+ if (dst == NULL) {
+ perror("Unable to allocate memory.\n");
+ return false;
+ }
+
+ printf(" Verifying string lengths at different alignments.\n");
+ char *src_align;
+ char *dst_align;
+ char *dst_ret;
+ for (size_t i = 0; i < STRING_ALIGN_LEN; i++) {
+ for (size_t copy_len = 0; copy_len <= MAX_STRING_TEST_SIZE; copy_len++) {
+ if (kStringAligns[i][0]) {
+ src_align = reinterpret_cast<char*>(getAlignedPtr(src+FENCEPOST_LENGTH, kStringAligns[i][0], kStringAligns[i][1]));
+ dst_align = reinterpret_cast<char*>(getAlignedPtr(dst+FENCEPOST_LENGTH, kStringAligns[i][2], kStringAligns[i][3]));
+ } else {
+ src_align = src;
+ dst_align = dst;
+ }
+ setString(src_align, copy_len);
+ memset(dst_align, 0, copy_len+1);
+
+ if (dst_align != dst) {
+ setFencepost(reinterpret_cast<uint8_t*>(&dst_align[-FENCEPOST_LENGTH]));
+ }
+ setFencepost(reinterpret_cast<uint8_t*>(&dst_align[copy_len+1]));
+
+ if (verbose) {
+ printf("Testing copy_len %u, src_align=%p[%d,%d], dst_align=%p[%d,%d]\n",
+ copy_len, src_align, kStringAligns[i][0], kStringAligns[i][1],
+ dst_align, kStringAligns[i][2], kStringAligns[i][3]);
+ }
+
+ dst_ret = test_strcpy(dst_align, src_align);
+ if (dst_ret != dst_align) {
+ printf("copy_len %u returned incorrect value: expected %p, got %p\n",
+ copy_len, dst_align, dst_ret);
+ return false;
+ }
+ if (memcmp(src_align, dst_align, copy_len) != 0) {
+ printf("copy_len %u failed to copy properly: src and dst aren't equal\n", copy_len);
+ return false;
+ }
+
+ if (dst_align != dst && !verifyFencepost(reinterpret_cast<uint8_t*>(&dst_align[-FENCEPOST_LENGTH]))) {
+ printf("copy_len %u fencepost before dst was overwritten\n", copy_len);
+ return false;
+ }
+
+ if (!verifyFencepost(reinterpret_cast<uint8_t*>(&dst_align[copy_len+1]))) {
+ printf("copy_len %u fencepost at end of dst was overwritten\n", copy_len);
+ return false;
+ }
+ }
+ }
+
+ printf(" All tests pass.\n");
+
+ return true;
+}
+
+bool runStrcatTest(char *(*test_strcat)(char *, const char *),
+ bool verbose) {
+ char *src = allocateString();
+ if (src == NULL) {
+ perror("Unable to allocate memory.\n");
+ return false;
+ }
+ char *dst = allocateString();
+ if (dst == NULL) {
+ perror("Unable to allocate memory.\n");
+ return false;
+ }
+
+ printf(" Verifying string lengths at different alignments.\n");
+ char *src_align;
+ char *dst_align;
+ char *dst_ret;
+ for (size_t i = 0; i < STRING_ALIGN_LEN; i++) {
+ for (size_t dst_len = 0; dst_len <= MAX_STRCAT_DST_SIZE; dst_len++) {
+ for (size_t copy_len = 0; copy_len <= MAX_STRING_TEST_SIZE; copy_len++) {
+ if (kStringAligns[i][0]) {
+ src_align = reinterpret_cast<char*>(getAlignedPtr(src+FENCEPOST_LENGTH, kStringAligns[i][0], kStringAligns[i][1]));
+ dst_align = reinterpret_cast<char*>(getAlignedPtr(dst+FENCEPOST_LENGTH, kStringAligns[i][2], kStringAligns[i][3]));
+ } else {
+ src_align = src;
+ dst_align = dst;
+ }
+ setString(src_align, copy_len);
+ memset(dst_align, 'd', dst_len);
+ memset(dst_align+dst_len, 0, copy_len+1);
+
+ if (dst_align != dst) {
+ setFencepost(reinterpret_cast<uint8_t*>(&dst_align[-FENCEPOST_LENGTH]));
+ }
+ setFencepost(reinterpret_cast<uint8_t*>(&dst_align[copy_len+dst_len+1]));
+
+ if (verbose) {
+ printf("Testing copy_len %u, dst_len %u, src_align=%p[%d,%d], dst_align=%p[%d,%d]\n",
+ copy_len, dst_len, src_align, kStringAligns[i][0], kStringAligns[i][1],
+ dst_align, kStringAligns[i][2], kStringAligns[i][3]);
+ }
+
+ dst_ret = test_strcat(dst_align, src_align);
+ if (dst_ret != dst_align) {
+ printf("dst_len %u, copy_len %u returned incorrect value: expected %p, got %p\n",
+ dst_len, copy_len, dst_align, dst_ret);
+ return false;
+ }
+ for (size_t j = 0; j < dst_len; j++) {
+ if (dst_align[j] != 'd') {
+ printf("dst_len %u, copy_len %u: strcat overwrote dst string\n",
+ dst_len, copy_len);
+ return false;
+ }
+ }
+ if (memcmp(src_align, dst_align+dst_len, copy_len+1) != 0) {
+ printf("dst_len %u, copy_len %u failed to copy properly: src and dst aren't equal\n",
+ dst_len, copy_len);
+ return false;
+ }
+
+ if (dst_align != dst && !verifyFencepost(reinterpret_cast<uint8_t*>(&dst_align[-FENCEPOST_LENGTH]))) {
+ return false;
+ }
+
+ if (!verifyFencepost(reinterpret_cast<uint8_t*>(&dst_align[dst_len+copy_len+1]))) {
+ return false;
+ }
+ }
+ }
+ }
+
+ printf(" All tests pass.\n");
+
+ return true;
+}
+
bool runMemcpyTest(void* (*test_memcpy)(void *dst, const void *src, size_t n),
bool verbose) {
- // Allocate two large buffers to hold the dst and src.
uint8_t *dst = reinterpret_cast<uint8_t*>(malloc(MAX_MEMCPY_BUFFER_SIZE));
uint8_t *src = reinterpret_cast<uint8_t*>(malloc(MAX_MEMCPY_BUFFER_SIZE));
if (dst == NULL || src == NULL) {
}
}
- int aligns[][4] = {
+ const int aligns[][4] = {
// Src and dst use pointers returned by malloc.
{ 0, 0, 0, 0 },
bool runMemsetTest(void* (*test_memset)(void *s, int c, size_t n),
bool verbose) {
- // Allocate one large buffer to hold the dst.
uint8_t *buf = reinterpret_cast<uint8_t*>(malloc(MAX_MEMSET_BUFFER_SIZE));
if (buf == NULL) {
perror("Unable to allocate memory.\n");
return false;
}
- int aligns[][2] = {
+ const int aligns[][2] = {
// Use malloc return values unaltered.
{ 0, 0 },
printf("Testing strlen...\n");
tests_passing = runStrlenTest(strlen, verbose) && tests_passing;
+ printf("Testing strcpy...\n");
+ tests_passing = runStrcpyTest(strcpy, verbose) && tests_passing;
+
+ printf("Testing strcat...\n");
+ tests_passing = runStrcatTest(strcat, verbose) && tests_passing;
+
return (tests_passing ? 0 : 1);
}