From db758708b46eef49bc24ca4926958a34b28c5376 Mon Sep 17 00:00:00 2001 From: Christopher Ferris Date: Thu, 11 Jul 2013 15:14:42 -0700 Subject: Add tests for strcpy and strcat. Also convert all of the different string length defines to a single string length macro. Move the string alignment loop to the top and make all alignment structures const. Merge from internal master. (cherry-picked from 1c33ae7ce88efc23b627f5fdb74afc461fc8e4f5) Change-Id: I973795cfff55975574dd1b17cc9b25d9f6932873 --- libc_test/main.cpp | 308 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 229 insertions(+), 79 deletions(-) diff --git a/libc_test/main.cpp b/libc_test/main.cpp index 3c57f41d..6e7b62f3 100644 --- a/libc_test/main.cpp +++ b/libc_test/main.cpp @@ -31,11 +31,39 @@ extern "C" { #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) { @@ -51,6 +79,24 @@ void *getAlignedPtr(void *orig_ptr, int alignment, int or_mask) { return reinterpret_cast(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(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; @@ -68,7 +114,7 @@ bool verifyFencepost(uint8_t *buffer) { } 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; } @@ -76,13 +122,13 @@ bool verifyFencepost(uint8_t *buffer) { 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]; @@ -112,14 +158,14 @@ bool doStrcmpExpectEqual(char *string1, char *string2, int align[4], 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) { @@ -129,8 +175,8 @@ bool doStrcmpExpectDiff(char *string1, char *string2, int diff_align[2], } 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 @@ -141,7 +187,7 @@ bool doStrcmpExpectDiff(char *string1, char *string2, int diff_align[2], } // 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]; @@ -153,7 +199,7 @@ bool doStrcmpExpectDiff(char *string1, char *string2, int diff_align[2], } 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; @@ -164,7 +210,7 @@ bool doStrcmpExpectDiff(char *string1, char *string2, int diff_align[2], 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; @@ -174,7 +220,7 @@ bool doStrcmpExpectDiff(char *string1, char *string2, int diff_align[2], } 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; } @@ -198,7 +244,7 @@ bool doStrcmpCheckRead(int (*test_strcmp)(const char *s1, const char *s2), 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); @@ -257,61 +303,23 @@ bool doStrcmpCheckRead(int (*test_strcmp)(const char *s1, const char *s2), 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(malloc(MAX_STRCMP_BUFFER_SIZE+1)); - char *string2 = reinterpret_cast(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 }, @@ -324,17 +332,17 @@ bool runStrcmpTest(int (*test_strcmp)(const char *s1, const char *s2), 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; } } @@ -390,22 +398,15 @@ bool doStrlenCheck(size_t size, char *string, int align, int or_mask, bool runStrlenTest(size_t (*test_strlen)(const char *), bool verbose) { - // Allocate two large buffers to hold the two strings. - char *string = reinterpret_cast(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 }, @@ -427,7 +428,7 @@ bool runStrlenTest(size_t (*test_strlen)(const char *), 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; } @@ -451,7 +452,7 @@ bool runStrlenTest(size_t (*test_strlen)(const char *), 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)); } @@ -481,9 +482,153 @@ bool runStrlenTest(size_t (*test_strlen)(const char *), 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(getAlignedPtr(src+FENCEPOST_LENGTH, kStringAligns[i][0], kStringAligns[i][1])); + dst_align = reinterpret_cast(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(&dst_align[-FENCEPOST_LENGTH])); + } + setFencepost(reinterpret_cast(&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(&dst_align[-FENCEPOST_LENGTH]))) { + printf("copy_len %u fencepost before dst was overwritten\n", copy_len); + return false; + } + + if (!verifyFencepost(reinterpret_cast(&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(getAlignedPtr(src+FENCEPOST_LENGTH, kStringAligns[i][0], kStringAligns[i][1])); + dst_align = reinterpret_cast(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(&dst_align[-FENCEPOST_LENGTH])); + } + setFencepost(reinterpret_cast(&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(&dst_align[-FENCEPOST_LENGTH]))) { + return false; + } + + if (!verifyFencepost(reinterpret_cast(&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(malloc(MAX_MEMCPY_BUFFER_SIZE)); uint8_t *src = reinterpret_cast(malloc(MAX_MEMCPY_BUFFER_SIZE)); if (dst == NULL || src == NULL) { @@ -502,7 +647,7 @@ bool runMemcpyTest(void* (*test_memcpy)(void *dst, const void *src, size_t n), } } - int aligns[][4] = { + const int aligns[][4] = { // Src and dst use pointers returned by malloc. { 0, 0, 0, 0 }, @@ -625,14 +770,13 @@ bool runMemcpyTest(void* (*test_memcpy)(void *dst, const void *src, size_t n), 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(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 }, @@ -734,5 +878,11 @@ int main(int argc, char **argv) { 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); } -- cgit v1.2.3